Java程式設計的邏輯(一)
目錄
Java程式設計的邏輯(一)
第一部分 程式設計基礎與二進制
第一章 程式設計基礎
1.1 資料變量
1.2 指派
1.2.1 基本資料類型
1.2.2 數組類型
1.3 基本運算
1.3.1 算數運算
第一部分 程式設計基礎與二進制
第一章 程式設計基礎
計算機是個機器,這個機器主要由CPU、記憶體、硬碟和輸入/輸出裝置組成。計算機上跑着作業系統,如windows或Linux或Mac,作業系統上運作着各類應用程式,如QQ、網易雲音樂、Office辦公軟體等等。
作業系統将時間分成很多細小的時間片,一個時間片給一個程式使用,另一個時間片給另一個程式使用,并頻繁地在程式間進行着切換。不過,在應用程式看來,整個機器資源好像都歸它使用,作業系統給它制造了這種假象。對程式員來說,編寫程式時并不需要考慮其他應用程式的影響,做自己的事情就好了。
應用程式看上去能做很多事情,能讀寫文檔、能播放音樂、能聊天、能玩遊戲、能下圍棋等,但本質上,計算機隻會執行預先寫好的代碼,這些指令也隻會操作資料或者裝置。所謂程式,基本上就是告訴計算機要操作的資料和執行的指令,即對什麼資料進行什麼操作。比如:
1)、讀文檔,就是将資料從磁盤加載到記憶體,然後輸出到顯示器;
2)、寫文檔,就是将資料從記憶體寫回磁盤;
3)、播放音樂,就是将音樂的資料加載到記憶體,然後寫到聲霸卡上;
4)、聊天,就是從鍵盤擷取到使用者輸入的聊天資料,放到記憶體,然後傳給然後傳給網卡,通過網絡傳給另一個人的網卡,再從網卡傳到記憶體,顯示在顯示器上。
基本上,所有資料都需要放到記憶體裡進行處理,程式的很大一部分工作就是操作記憶體中的資料。那麼如何表示和操作資料呢?本章注重講解一些基礎知識。資料在記憶體中基本是以二進制表示的,不友善操作,為了友善操作資料,進階語言中引入了資料類型和變量的概念
1.1 資料變量
資料類型用于對資料分類,以便于了解和操作。對Java語言而言,有如下基本資料類型。
- 整數類型:有四種整形 byte / short / int / long,,分别有不同的取值範圍;
- 小數類型:有兩種類型 float / double,有不同的取值範圍和精度;
- 字元類型:char 表示單個字元;
- 布爾類型:boolean,表示真假。
基本資料類型都有對應的資料類型,數組表示固定長度的同種資料類型的多條記錄,這些資料在記憶體中連續存放。
為了操作資料,需要把資料放置到記憶體中。所謂記憶體在程式看來就是一塊有位址編号的連續的空間,資料存放到某個位置後,為了友善地找到和操作這個資料,需要給這個位置起一個名字。程式設計語言通過變量這個概念表示這個過程。
聲明一個變量,比如 int a,其實就是在記憶體中配置設定了一塊空間,這塊空間存放int資料類型,a 指向這塊記憶體空間所在的位置,通過對 a 操作即可操作 a 指向的記憶體空間,比如 a=5 這個操作即可将 a 指向的記憶體空間的值改為 5。
之是以叫 “變” 量,是因為它表示的是記憶體中的位置,這個位置存放的值是可以變化的。
雖然變量的值是可以變化的,但是變量的名字是不變的,這個名字應該代表程式員心目中這塊記憶體空間的意義,這個意義應該是不變的。比如,變量 int second 表示時鐘秒數,在不同時間可以被賦予不同的值,但它表示的始終是始終秒數。之是以說應該,是因為這不是必須的,如果一定要為一個名為 age 的變量賦予身高的值,計算機也拿你沒有辦法。
重要的話再說一遍!變量就是給資料起名字,友善找不同的資料,它的值可以變,但含義不應變。
1.2 指派
聲明變量之後,就在記憶體配置設定了一塊位置,但這個位置的内容是未知的,指派就是把這塊位置的内容設為一個 确定的值。Java中基本資料類型、數組、對象的指派有明顯不同,本節介紹基本類型和數組的指派,對象的指派在第三章再進行介紹。
1.2.1 基本資料類型
(1)整數類型
整數類型有byte、short、int 和 long,分别占1、2、4、8,取值範圍如下表所示。
類型名 | 取值範圍 | 類型名 | 取值範圍 |
byte | -2^7 ~ 2^(7-1) | int | -2^31 ~ 2^31-1 |
short | -2^15 ~ 2^15-1 | long | -2^63 ~ 2^63-1 |
我們用^表示指數,2^7表示2的7次方。這個範圍我們不需要記得那麼清楚,有個大概的範圍認知就好了。
指派形式很簡單,直接把熟悉的數字常量形式指派給變量即可,對應的記憶體空間的值就從未知變成了确定的常量。但常量不能超過對應類型的表示變量。
byte b = 23;
short s = 3333;
int i = 9999;
long l = 32323;
但是,在給long類型變量指派時,如果常量超過了int的表示範圍,需要在常量後面添加大寫或者小寫字母L,即L或者l,例如:
long a = 3232343433L;
之是以需要添加L或者l,是因為數字常量預設為int類型。
(2)小數類型
小數類型有 float 和 double,占用的記憶體空間分别是4和8位元組,有不同的取值範圍和精度,double表示的範圍更大,精度更高,具體如下表所示:
類型名 | 取值範圍 | 類型名 | 取值範圍 |
float | 1.4E-45 ~ 3.4E+38 -3.4E+38 ~ -1.4E-45 | double | 4.9E-324 ~ 1.7E+308 -1.7E+308 ~ -4.9E-324 |
取值範圍看上去很奇怪,一般也不需要記住,有個大概的印象就好了。E表示以10為底的指數,E後面的+号和-号代表正指數和負指數,例如:1.4E-45表示1.4乘以10的-45次方。
對于double,直接把熟悉的小數表示指派給變量即可,例如
double d = 333.33;
但對于float,需要在數字後面加大寫字母F或者小寫字母f,例如:
float f = 333.33f;
這是由于小數常量預設是double類型。
除了小數,也可以把整數直接指派給float或double,例如:
float f = 33;
double d = 3333333333333L;
(3)布爾類型
布爾類型(boolean)真的很簡單,直接使用 true 或 false 指派,分别表示真和假。例如:
boolean a = true;
a = false;
(4)字元類型
字元類型 char 用于表示一個字元,這個字元可以是中文字元,也可以是英文字元,char 占用的記憶體空間是兩個位元組。指派時把常量字元用單引号括起來,不用雙引号。例如:
char a = 'a';
char b = '碼';
大部分的常用字元用一個char 就可以表示,但有的特殊字元用一個 char 表示不了。
同時變量也可以給變量指派,例
int a = 10;
int b = a;
1.2.2 數組類型
基本的數組有三種指派形式,如下所示:
1. int[] arr = {1,2,3};
2. int[] arr = new int[]{1,2,3};
3. int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
第一種,第二種都是預先知道數組的内容,第三種是先配置設定長度,然後再給每個元素進行指派。第三種形式中,即使沒有給每個元素指派,每一個元素也有一個預設值,這個預設值跟數組類型有關,數值類型的預設值為0,boolean類型的預設值為false,char類型的預設值為空字元。
數組長度可以動态确定,如下所示:
int[] arr = ...;
int arr = new int[length];
數組長度雖然可以動态确定,但是一旦确認就不能改變。數組有一個 length 屬性,但隻能讀,不能改。還有一個小細節,不能在給定的初始值的同時給定長度,以下格式是不允許的:
int[] arr = new int[3]{1,2,3};
1.3 基本運算
有了初始值之後,可以對資料進行運算。運算不同的類型,不同的類型支援的運算也不一樣,本節中主要介紹java中基本類型資料的主要運算。
- 算數運算:主要是日常的加減乘除。
- 比較運算:主要是日常的大小比較。
- 邏輯運算:針對布爾值進行運算。
1.3.1 算術運算
算術運算符有加(+)、減(-)、乘(*)、除(/),另外還有取模運算符 %,以及自增(++)和自減(--)運算符。取模運算适用于整數和字元類型,其他算術運算适用于所有資料類型和字元類型。大部分算術運算都符合我們數學常識。
減号(-)通常用于兩個數相減,但也可以放在一個數前面,例如 - a,這表示改變 a 的符号,原來的正數會變為負數,原來的負數會變為正數,這也是符合我們常識的。
取模(%)就是數學中的求餘數。例如 5%3 = 2 10%5 = 0
自增(++)和自減(--),是一種快捷方式,是對自己進行加一和減一操作
加、減、乘、除 大部分情況和數學運算是一樣的。都很容易了解,但是有一些需要注意的地方,而自增、自減稍微複雜一些,下面我們做一點解釋。
1、加、減、乘、除 注意事項
運算時要注意結果的範圍,使用恰當的資料類型。兩個正數都可以用 int 類型,但相乘的結果可能會超出,超出後結果會令人困惑,例如
int a = 2147483647 * 2; // int 的最大值是 2147483647
a 的結果是 -2,為什麼是 -2 我們暫不解釋,要避免這種情況,我們的結果類要使用 long, 但隻改為 long,也是不夠的,因為運算還是預設按照 int 類型進行,需要至少将一個資料表示為 long 類型,即在後面L或l,下面這樣才會出現期望的結果:
long a = 2147483647 * 2L;
另外,需要注意的是,整數相除不是四舍五入,而直接舍去小數位,例如:
double d = 10 / 4;
結果是 2 而不是 2.5,如果要小數進行運算,需要将至少一個數表示為小數形式,或者使用強制類型轉化,即在數字前面加(double),表示将數字看做 double 類型,如下所示的任意一種資料形式都可以;
2、小數計算結果不精确
無論是使用 float 還是 double,進行運算時都會出現一些非常令人困惑的現象,比如:
float f = 0.1f*0.1f;
System.out.println(f);
這個結果看上去應該是0.01,但實際上卻會輸出0.010000001,後面多了個1。換用 double 看看:
double d = 0.1*0.1;
System.out.println(d);
螢幕輸出0.010000000000000002,一連串的0之後多了一個2,結果也不準确。
看似這麼簡單的運算,怎麼計算機的結果并不精确呢?但事實就是這樣,這就需要我們了解 float 和 double 的二進制,這塊我們下節内容分析。
3、自增(++)/ 自減(--)
自增 / 自減是對自己做加一或減一的操作,但每個都有兩種形式,一個是放在變量後,一個是放在變量前。
當沒有其他運算的情況下。這兩種模式沒有差別,但是一旦有其他運算加入的情況下,變量後是先用原來的值進行其他操作,再進行自增,或者自減;變量前這種模式,就是先進行自增或者自減運算,然後将結果值和其他值進行計算。
自增 / 自減運算是一種 “快捷” 操作,是讓程式員少些代碼的,但遺憾的是,由于比較奇怪的文法和詭異的行為,給初學者帶來了一些困惑。
1.3.2 比較運算
比較運算就是計算兩個值之間的關系,結果是一個boolean類型的值,比較運算符适用于所有數值類型和字元類型。
比較操作符有大于(>)、大于等于(>=)、小于(<)、小于等于(<=)、等于(==)、不等于( != )。
此處需要注意的就是,等于号并不是一個=。因為一個等号=已經被指派運算占用了。
如果需要比較一個數組的話,需要比較數組裡面每一個字段的值是否相等。
1.3.3 邏輯運算
邏輯運算根據資料的邏輯關系,生成一個 布爾值 true 或者 false。邏輯運算隻可應用于 boolean 類型的資料,但比較運算的結果是布爾值,是以其他類型資料的比較結果可進行邏輯運算。
邏輯運算符具體有以下這些。
- 與(&):兩個都為 true 結果才是 true,隻要有一個是 false 就是 false。
- 或(|):隻要一個為 true 就是 true,都是 false才是 false。
- 非(!):針對一個變量,true 會變為 false, false 會變為 true。
- 異或(^):兩個相同為 false, 兩個不相同為 true。
- 短路與(&&):和 & 類似,不同之處稍後解釋。
- 短路或(||):和 | 類似,不同之處 稍後解釋。
邏輯運算的大部分都是比較直覺的,需要注意的是 & 和 &&,以及 | 和 || 的差別。如果隻是進行邏輯雲散,他們都是相同的,差別在于有其他操作的情況下,例如:
boolean a = true;
int b = 0;
boolean flag = a | b++ > 0;
因為 a 為true, 是以 flag 也為 true,但 b 的結果為1,因為 | 後面的式子也會計算,即使 隻看a 已經知道了flag 的結果,還是會進行後面的運算。而 || 則不同,它運算到 a 的時候知道結果的情況下,就不會繼續進行後面的運算了。
關于這塊的内容,同學們如果想了解更多資訊,可以加群了解哦,群号:834223478。