《Java JDK8學習筆記》讀書筆記(3)

第3章 基礎語法

3.1 類型、變量與運算符

Java是支持面向對象的語言,但我們還是要先了解一些基本語法元素。由於每種語言都有其誕生的宗旨與演化過程,對這些基本語法元素,也就會有其獨特的特性。
3.1.1 類型
在Java中,並非所有的東西都當對象來處理

(默然說話:對,Java的確並非是象C#那樣完全面向對象的語言,它包含了一些非面向對象的概念,比如這裏要談到的數據類型與所佔用內存大小的問題,這主要是爲了提高Java程序的執行效率而做出的犧牲。)

。基本上,Java可區分爲基本數據類型(Primitive Type)和引用數據類型(Reference Type)。
這裏介紹基本類型,第4章介紹引用類型。
所謂基本數據類型,就是在使用時,得考慮一下數據用多少內存長度來存比較經濟,利用程序語法告訴JVM,然後由JVM爲你在內存中進行配置與管理。Java中的基本數據類型主要有整數、字節、浮點數、字符與布爾。

  • 整數:就是整數嘍,小學重點學的是自然數,整數就是自然數,零,負整數的集合。它是一系列非連續的數字(默然說話:數學用語:非線性),在座標軸上是一個一個獨立的小點。在Java中爲了更好的使用內存,又把整型細分爲short(佔2個字節)、int(佔4個字節)、long(佔8個字節)三種類型。

(默然說話:字節就是內存的一個長度單位,1字節表示能裝下一個字符的內存空間,字節也可以表示數字——其實本來就是數字——字節越長,能表示的數字也就越大)。

  • 字節:byte,長度是1字節。在需要逐字節處理數據時(圖像,視頻,音樂等各種二進制編碼的數據)就會使用byte。同樣,也可用於表示整數,範圍是-128-127。
  • 浮點數:主要用來儲存小數數值,可分爲float(佔4字節)和double(佔8字節)。double比float可以裝下的數字大得多,可表示的精確度也比較大。
  • 字符:char用來儲存’A’、’B’、’林’等字符符號。在JDK8中,Java的字符采用Unicode6.2.0編碼,JVM結果採用UTF-16 Big Endian,所以每個字符類型佔2字符,漢字字符與英文字符在Java中同樣都是用雙字節儲存。
默然說話:編碼?Unicode?UTF?建議先看看以下文件(《哪來的純文本文檔?》和《Unicode與UTF》)
http://openhome.cc/Gossip/Encoding/TextFile.html
http://openhome.cc/Gossip/Encoding/UnicodeUTF.html
  • 布爾:boolean類型可以表示true與false,分別代表邏輯的“真”與“假”。在Java中不用在意boolean類型的長度,因爲你也無法將boolean類型與其他類型做運算。

每種類型的內存長度不同,可儲存的數值範圍也就不同。例int能儲存-2147483648~2147483647,如果存儲值超出了範圍,就稱爲溢出(Overflow),會造成程序出現錯誤。API使用了常量來記錄各種類型的邊界——也就是最大值和最小值,下面的程序可以實現。

package cn.com.speakermore;

/**
 *各基本數據類型的範圍
 * @author 默然說話
 */
public class Range {
    public static void main(String[] args){
        System.out.println("類型        \t最小值               \t最大值");
        //整數範圍
        System.out.println("Byte     \t"+Byte.MIN_VALUE+"               \t"+Byte.MAX_VALUE);
        System.out.println("Short    \t"+Short.MIN_VALUE+"              \t"+Short.MAX_VALUE);
        System.out.println("Integer  \t"+Integer.MIN_VALUE+"            \t"+Integer.MAX_VALUE);
        System.out.println("Long     \t"+Long.MIN_VALUE+"\t"+Long.MAX_VALUE);
        //小數範圍
        System.out.println("Float    \t"+Float.MIN_VALUE+"              \t"+Float.MAX_VALUE);
        System.out.println("Double   \t"+Double.MIN_VALUE+"             \t"+Double.MAX_VALUE);
        //字符範圍
        System.out.println("Character   \t"+(int)Character.MIN_VALUE+"                  \t"+(int)Character.MAX_VALUE);
        //布爾的兩個值
        System.out.println("Boolean   \t"+Boolean.TRUE+"                \t"+Boolean.FALSE);
    }
}

結果如下:
各基本數據類型的範圍
圖3.1各基本數據類型的範圍
對於初學Java的人,會看到一些新的語法與API在裏面。
“//”符號的意思就是註釋的一種,在Java中一共有三種註釋,雙斜槓“//”是單行註釋,也就是一次只能註釋掉一行。(默然說話:註釋的意思,就是用來說明或記錄程序中的一些注意事項的語句,這些都是給人看的,機器是不管它們的,所以在行的開頭加上“//”,機器就會忽略這一行的內容。)
“/”與“/”是另一種常見的註釋,它叫多行註釋,也就是它能註釋掉從“/”與“/”之間的所有內容,機器會完全忽略斜槓星與星斜槓之間的所有內容。
不過要注意多行註釋是不能嵌套的,如下:

/*  註釋1:OOXX
    /*註釋2:XXOO
    */
*/

機器會認爲倒數第二個“/”是註釋的結束,而最後一個“/”是錯誤的語法。從而報錯。
System.out.println()是標準API(默然說話:API就是“應用程序接口”的英文縮寫。用人話說,應用程序接口就是可以在我們所寫的代碼中可以調用的、現成的代碼。再簡單點:API就是寫好的代碼!!!現在明白了吧?再舉個例子:你寫了個代碼,它可以在別的代碼裏被調用,OK!恭喜你!你寫了一個API!!),它的作用就是進行一個文字的輸出,其中print就是輸出的意思,後面的ln是line的縮寫,意思是輸出一行,也就是帶換行符進行輸出,這句代碼執行完畢之後會自動換一行,這樣能讓我們看清楚輸出的內容。
你們還應該看到我在程序裏打了許多的空格和\t,這些是用來調整格式的。以便讓輸出的內容顯得整齊好看些。\t的意思就是添加一個表格列,也就是四個空格的距離。
最後就是好多的加號“+”,這裏是進行字符串的連接,把所有的內容連接成一個字符串,以進行輸出。
3.1.2 變量
如果我們要編寫程序,就會需要保存數據,如果要保存數據,就需要使用內存。內存就是用來存儲數據的嘛。可是,你怎麼告訴計算機,我要使用一塊內存呢?答案就是:使用變量。變量的使用要遵守一定的語法規則:先看例子:

int number=10;
double PI=3.14;
System.out.println(number);
System.out.println(PI);
System.out.println(number);

這個片段的第1行在告訴機器,我要有一塊內存,我把它叫number,可以放int類型的數據,使用“=”賦值運算符指定number變量的值爲10。(默然說話:注意“=”不讀作“等於”而讀用“賦值”,非常重要,非常重要,非常重要!
1. 基本規則
對於基本類型來說,想要聲明何種類型的變量,就使用byte、short、int、long、float、double、char、boolean等關鍵字來聲明。變量命名時要注意:它不可以使用數字作爲開頭,也不可以使用除了下劃線(_)和以外的任何特殊字符開頭(如!@#%……&*()——+)。第二個開始的字符可以是字母,數字,下劃線和 。另外,變量名不能使用Java已定義的關鍵字。如,public、static、int、double等就不能作爲變量的名字使用。
變量命名的規範主要以清楚易懂爲主。初學者最易犯的問題就是隨便用一些簡單字母來作爲變量名稱,這其實就是讓製造一個讓自己在這一行呆不下去的陷阱。因爲這樣寫出來的代碼,別人看不懂,時間一長,自己也看不懂了。連代碼都看不懂了,你還呆在這一行幹嘛?呆着發呆麼?另外也會造成自己寫不出大規模的代碼,基本上超過300行代碼,用簡單變量名就會出現大量重名的情況,也會出現變量用途不清的問題(默然說話:無數學員先烈已經用他們的事蹟告訴我,如果你用簡單字母,你就是找(er)屎(bi)!!這也讓我反思自己的教學代碼。現在即使是寫個一兩行的代碼,也儘量保證自己的變量名是有意義的,以做好模範帶頭作用,感謝那些學員先烈們,致以最高的敬意!)。
在Java業內,命名現在已經有了基本統一的規範

(默然說話:儘快按此養成習慣,你就打好了年薪百萬的基礎!)

,這個命名還有個很有意思的名字,叫駝峯命名法(Camel Case),它規定了變量命名以小寫字母開頭,第二個單詞開始,首字母大寫。`

(默然說話:最好使用英文單詞,不要放棄學習英文的機會呀,如果實在不願意,那也請使用全拼,這樣減少同音字帶來的意思理解上的偏差`)

例如:

int numberOfStudent;
int length
int niDeXingMing

我們到目前爲止的代碼都是寫在main()方法中的,在方法中聲明的變量稱爲局部變量。在Java中聲明一個局部變量,就會爲變量配置一塊內存,但Java不會爲局部變量的內存空間進行處理,所以當你聲明瞭一個局部變量之後,未對它進行賦值就使用的話,會得到一個錯誤信息。
變量使用錯誤:尚未初始化
圖3.2 變量使用錯誤:尚未初始化

(默然說話:順便解釋一下初始化的意思:初始化就是在聲明變量的時候同時對它進行賦值。還有個提法是:初始化就是第一次給變量賦值。不過我個人比較傾向於前者,因爲在Java裏,變量的第一次賦值是可以在聲明的同時進行的,也就是可以把變量的聲明和賦值寫成一條語句。例如:int
i=10;而絕大多數情況下,我們也是這樣在Java裏初始化變量的。)

如果在指定變量值之後,就不想再改變變量值,可以在聲明變量時加上final限定,如果後續自己或別人不小心修改了final變量,就會出現編譯錯誤。
變量使用錯誤:常量不能被第二次賦值
圖3.3變量使用錯誤:常量不能被第二次賦值
被final修飾的變量是不能被第二次賦值的,它被要求在聲明的同時必須給它賦值(也就是聲明和賦值必須寫在一個分號——分號代表語句結束——之內。)並且不能進行第二次的賦值。因爲它的值不能被修改,所以我們又把用final修飾的這種特殊的變量稱爲常量。“常”就是“一直這樣,無法被修改”的意思。
2. 字面常量
在Java中寫下一個值,如我們前面給變量賦值的那個“值”,被稱爲字面常量。在整數字面常量表示上,除了十進制表示之外,還可以使用八進制或十六進制表示。特點就是八進制在最前面加0,十六進制在最前面加0x。例如下面的代碼:

  int number1=12;//十進制:12
  int number2=0xC;//十六進制:還是12
  int number3=014;//八進制:還是12
  System.out.println("number1="+number1);//十進制輸出number1
  System.out.println("number2="+number2);//十進制輸出number2
  System.out.println("number3="+number3);//十進制輸出number3

它的輸出結果是:
關於字面常量的使用
圖3.4 關於字面常量的使用
從上面可以看到,字面常量可以有很多種表達方式,但它們的結果是一樣的。
如果你要表示字符,你可以使用單引號(’)括住字符。

char ch=’S’;
char name=’林’;

這裏要注意,單引號內只能是一個字符,不能寫多個。如果你需要寫多個字符,則使用雙引號括住內容,這叫做字符串。

String uname=”默然說話”;

需要特別註明的是,String不是一個基本數據類型,它是屬於對象型的數據類型。
在Java代碼我們還會用到叫做“轉義字符”的字面常量。比如單引號,它在Java就是字符類型的標誌,那如何輸出一個單引號呢?如果你直接打單引號,計算機會認爲你有語法錯誤,因爲計算機已經接受了單引號是字符類型的標誌,所以我們只能使用另一個符號來代表字符單引號,這組符號通常都用斜槓(\)來開頭,見下表:
表3.1 常用轉義符號

轉義符 說明
\ 字符斜槓
\’ 字符單引號
\” 字符雙引號
\uxxxx 十六進制數指定的Unicode字符,x是十六進制數字
\xxx 八進制指定的Unicode字符,x是八進制數字
\b 退格符(目前基本沒用)
\f 換頁符(目前基本沒用)
\n 換行符
\r 新行符(光標移到行首)

還有兩個較爲特殊的字面量,就是邏輯運算裏會用到的真和假,記作true和false。在計算機裏,它們被稱爲布爾類型(boolean)。
3.1.3 運算符
程序爲運算而生,程序開始,運算開始,程序結束,運算結束。而運算是要通過運算符來完成的。
Java的運算符可以分爲算術運算、關係運算、邏輯運算和位運算四大類型。
1. 算術運算
算術運算就是生活中的數學基本運算,也就是加、減、乘、除這類運算符。具體見下表:
表3.2 算術運算符

運算符 說明
+
-
*
/
%
++ 自增1
自減1
+= 指定自增
-= 指定自減
*= 指定自乘
/= 指定自除
%= 指定取模

算術運算的符號要注意,乘法沒有使用乘號,而是使用了星號。算術運算的規則與我們數學課所學一致,先乘除,後加減,如果你要改變運算優先級,需要加上小括號,例如:

System.out.println(2+2+8/4);//結果是6
System.out.println((2+2+8)/4);//結果是3

上面兩句代碼的輸出是不同的,因爲運算的步驟不一樣了。
除了我們在數學課所學到的一些計算,Java還有許多新增加的算術運算,例如取模(%),這個符號只能在兩個整數之間進行,它的結果是整除之後的餘數。例如:

System.out.println(5%2);//結果是1

此外,還有就是著名的++和–了。這是從C語言一直傳下來的,它只能和變量配合使用,作用就是把變量的值取出,加1,然後在再保存給變量(我們稱之爲賦值)。

int i=1;
i++;//相當於i=i+1
System.out.println(i);//結果是2
--也是一樣的,把變量的值取出,減1,然後再保存給變量。
int i=1;
i--;//相當於i=i-1
System.out.println(i);//結果0

+=非常類似於++運算,只是++運算只能加1,而+=運算可以指定加幾,例如:

int i=1;
i+=3;//相當於i=i+3;
System.out.println(i);//結果是4

其他指定運算符相似,不再一一說明。
2. 關係運算
數學上有大於、等於、小於、大於等於、小於等於、等於和不等於的比較運算,這些運算符被稱爲關係運算符。
表3.3 關係運算符

運算符 說明
> 大於
< 小於
>= 大於等於
<= 小於等於
== 等於(兩個等號)
!= 不等於(驚歎號等號)

這些運算符的規則也和數學上的規則是一至的,運算符可以作用於整數,小數,產生的結果只會有兩個:真(true)和假(false)。代碼如下:

public class Comparison {
    public static void main(String[] args){
        System.out.println("10>5的結果:"+(10>5));//10>5要加小括號,因爲比較運算符的優先級沒有算術運算符高
        System.out.println("10>=5的結果:"+(10>=5));
        System.out.println("10<5的結果:"+(10<5));
        System.out.println("10<=5的結果:"+(10<=5));
        System.out.println("10==5的結果:"+(10==5));
        System.out.println("10!=5的結果:"+(10!=5));
    }
}

運行結果如下:

run:
10>5的結果:true
10>=5的結果:true
10<5的結果:false
10<=5的結果:false
10==5的結果:false
10!=5的結果:true
成功構建 (總時間: 1 秒)

注意,等於比較是使用兩個等號(==),一個等號(=)是表示賦值,它的意思就是把等號右邊的值保存到等號的左邊變量中。所以,如果你寫1=3,Java就會報錯的,因爲賦值號(=)的左邊只能是變量。

(默然說話:其實上面的代碼並沒有什麼實際的應用意義,在實際的應用中,真和假只是用來決定程序的執行路徑的,並不需要顯示出來。比較運算通常也是和if、for、while等關鍵字連用的,這裏的代碼屬於純教學代碼,僅供觀賞,基本理解即可,不用深入研究。)

3. 邏輯運算
如果我們要綜合多個條件判斷,得出最終的結果,我們就必須使用到邏輯運算符,邏輯運算符有三個,一般我們稱爲“與”、“或”、“非”。
表3.4 Java的邏輯運算符

運算符 說明
&& 邏輯與
|| 邏輯或
! 邏輯非(只有一個驚歎號)

邏輯運算要注意的問題是,參與邏輯運算的值只有布爾值,也就是說,邏輯運算符只能對真和假進行運算。邏輯運算最後的結果也是真和假,所以我們說,邏輯運算符就是把多個真假的關係運算爲一個真假。
上面的話說得太理論,舉幾個具體的例子。
生活經常會有許多連續的判斷,比如成績上80且數學有90分爲優秀學生,成績90分以上或有20人推薦可以成爲三好學生。從前面的兩個例子可以看出,第一個例子要2個條件均成立,才能得到優秀學生的稱號,而第二個例子只要有一個條件成立,就能得到三好學生的稱號。第一個例子就是我們邏輯運算“與”,第二個例子就是我們的“或”運算。
成績>=80&&數學>=90
成績>90||推薦人>20
“非”運算就是取反,類似於我們平時說的“不”,高取反,就是“不高”,用Java語言來描述就是:
!高
關於與或的邏輯運算結果通常會有一張表,簡單說,就是與(&&)運算要求參與運算的所有值都爲真,結果纔會是真,或(||)運算只要有一個條件爲真,結果就會是真。
表3.5 Java邏輯運算的規律

邏輯數1 邏輯數2 &&結果 ||結果
True True True True
True False False True
False True False True
False False False False

另外,說點Java語言中特有的,叫做“短路運算(Short-Circuir Evaluation)”。也就是當進行多次的邏輯運算時,由於前面提到過的規律,與運算如果第一個表達式得到一個False,它就不會再計算另一個表達式了,而或運算同樣,如果第一個表達式得到一個True,它也不會再計算另一個表達式了。我們可以利用這個特點,來解決程序中的許多bug,例如:

if(user!=null&&user.getName().eqauls(“Jack”)){
    //做某事
}

上面是一個判斷用戶的名稱叫Jack的語句,它會有一個問題,就是如果user對象爲空,則user.getName()就會報NullPointerException的異常,這是很頭疼的一件事情,因爲在實際程序運行過程,很難保證user對象不會爲空。而在前面加上了user!=null這個判斷之後,如果user!=null爲False(也就是說user爲空),則Java就不會去執行user.getName()這句代碼,不執行,就沒有異常了。這就巧妙地利用了“短路運算”,避免一些煩人的異常問題。
邏輯或是類似的道理,這裏就不再舉例了。
4. 位運算
位運算是如今在應用開發的代碼中很少用到的部分,這裏作簡單介紹。不感興趣的同學可以跳過。
位運算有與、或、異或和補四種運算。
這種運算是按位進行的運算。也就是說,它不關心你的數字是多少,它只按你這個數字的二進制形式按位的順序進行邏輯運算。由於生活中極少用到二進制的運算,所以位運算也就很少接觸。不過,這也是Java裏的一個特點,也有它的用處(比如在加解密算法中,就是很常用的)。
表3.6 Java位運算符

運算符 說明
& 按位與
| 按位或
^ 按位異或
~ 按位補

位運算是逐位運算,所以如果你使用十進制方式來表示,你會完全不明白位運算做了什麼。所以位運算第一步總是把十進制數轉化爲二進制數,再對位進行邏輯運算。因爲二進制數只有2個數,一個是1,一個是0,所以我們可以把1看成真,把0看成假,然後根據前面我們所講過的邏輯運算規則進行運算。算完之後再轉爲十進制,這樣我們就瞭解到最終的結果用十進制表示是什麼樣
5. 條件運算
Java有個條件運算符,使用方式如下:
條件?條件爲真時的返回值:條件爲假時的返回值
這個表達式在一些情況下很有用處,可以縮短我們的代碼,使表達簡單化,但缺點就是會讓人看不太懂。比如判斷一個數是否爲偶數,如果用if…else可以寫成這樣:

if(number%2==0){
    System.out.println(“該數爲偶數”);
}else{
    System.out.println(“該數爲奇數”);
}

如果使用條件運算符,則可以寫成這樣:

String result=number%2==0?”偶數”:”奇數”
System.out.println(“該數爲”+result);

代碼大大縮短,但是,的確沒有if…else那麼容易明白。
3.1.4 類型轉換
前面已經講過,變量標識了一塊內存,我們可以使用變量對計算機的內存進行值的保存。聲明變量,就是聲明瞭一塊內存用來裝值。那接下來要說的,就是這塊內存應該多大?
無論你的內存有多大,總有被用完的時候,所以,如何高效率的使用內存就擺上了桌面。要高效率的使用內存,就得給每個變量分配一塊大小合適的內存,如何完成這一工作?這就是由數據類型來決定的。所以當我們談到數據類型的時候,我們總會說這個類型有多大的內存。如下表:
表3.7 數據類型所佔內存大小

數據類型 大小
byte 1字節
char 2字節
short 2字節
int 4字節
long 8字節
float 8字節
double 16字節

當我們進行賦值或計算時,由於計算機要求類型一致才能進行賦值和運算,所以就存在類型轉換的情況。類型轉換的基本原則有兩條:第一是類型之間要兼容,第二是把小數放到大類型會自動完成(自動類型轉換),把大數放到小類型裏就必須強制進行(強制類型轉換)。
比如:

float PI=3.14

因爲Java語言默認把小數看作是double類型,而double(16字節)類型比float(8字節)類型要大。所以計算機會報錯。
需要強制類型轉換的報錯信息
圖3.5 需要強制類型轉換的報錯信息
正如錯誤消息所說,因爲大數放到小類型中,有可能會不夠裝,造成丟失精度或出現錯誤,編譯器並不想爲此後果負責,所以它告訴你,並要你親自確認這個轉換是你自己願意的。這就是所謂的強制類型轉換。我們可以用兩種方式進行,較通用的方式就是在大數之前打小括號,括號中寫要轉換的類型,如下:

float PI=(float)3.14;

另一種寫法是在大數的末尾加個F(大小寫均可),如下:

float PI=3.14f;

3.2 流程控制

現實生活中需要解決的事情很多,在計算機發明之後,想要使用計算機解決的需求也是各式各樣:這就要求使用各種條件判斷語句來定義程序執行的流程。
3.2.1 if…else
語法:

if(條件式){
    語句1;
}else{
    語句2;

條件式的運算結果爲true時,會執行語句1,否則執行語句2。

package cn.com.speakermore;

/**
 * 判斷一個數的奇偶
 * @author mouyo
 */
public class Odd {
    public static void main(String[] args){
        int input=10;
        int remain=input % 2;//取餘數
        if(remain==1){
            System.out.println(input+"是一個奇數");
        }else{
            System.out.println(input + "是一個偶數");
        }
    }
}

說明:範例中的Input變量,實際上可以由用戶輸入取得值,具體在第4章說明
還有一種多重判斷語句,語法如下:

if(條件式1){
    語句1;
}else if(條件式2){
    語句2;
}else{
    語句3;
}

如果條件式1不滿足,就執行條件式2的判斷,如果滿足就執行語句2,然後跳過整個多重判斷,執行後面的語句。換個說法,多重判斷語句就是找到第一個條件式爲真之後的語句去執行,執行完畢之後,直接執行後面的語句。不會去執行條件式爲真之後的任何判斷語句。
例如,應用在處理學生的成績等級問題:

package cn.com.speakermore;

/**
 * 等級多重判斷
 *文件名:Level.java
 * @author mouyo
 */
public class Level {
    public static void main(String[] args){
        int score=88;
        char level;
        if(score>=90){
            level='A';
        }else if(score>=80){
            level='B';
        }else if(score>=70){
            level='C';
        }else if(score>=60){
            level='D';
        }else{
            level='E';
        }
        System.out.println("得分等級:"+level);
    }
}

3.2.2 switch
在JDK 7前,switch只可用於比較整數、字符、Enum(默然說話:Enum就是枚舉類型),從JDK 7開始,增加了對字符串的比較。Enum後面會再詳細說明。
switch的語法:

switch(變量或表達式){
case 整數、字符、字符串或Enum:
    語句;
    break;
case 整數、字符、字符串或Enum:
    語句;
    break;
……
default:
    語句;
    break;
}

首先就是switch關鍵字,全小寫,後面跟小括號和大括號。小括號中寫需要和case進行比較值的變量或表達式,值只能是整數、字符、字符串或Enum,變量和表達式取到值之後就會開始與case後設定的整數、字符、字符串或Enum常量值進行比較(默然說話:注意!case後的常量值類型必須與小括號裏的變量類型或表達式執行結果的數據類型一致,否則報語法錯誤),如果相等就執行之後的語句,直到遇到了break才跳出switch語句。如果沒有符合的整數、字符、字符串或Enum,則執行default後面的語句,直到遇到了break才跳出switch語句。default語句是可以省略的。
來看看前面範例的Level類,如何改用switch運行。

package cn.com.speakermore;

/**
 * switch方式的得分等級
 * 文件名:Level2.java
 * @author mouyo
 */
public class Level2 {
    public static void main(String[] args){
        int score=86;
        //很聰明的做法,因爲我們是按分數段處理,所以除以10就可去掉個位數,保留10位數,
        //這樣就可以把大於的情況轉換爲等於的情況了
        int quotient=score/10;
        char level;
        switch(quotient){
            case 10:
            case 9:
                level='A';
                break;
            case 8:
                level='B';
                break;
            case 7:
                level='C';
                break;
            case 6:
                level='D';
                break;
            default:
                level='E';
                break;
        }
        System.out.println("得分等級:"+level);
    }
}

在這個程序中,使用除法並取得運算後的商,如果大於90,除以10就只會得到9或10(100分除以10,商就是10),在case 10中沒有任何代碼,也沒有break,所以繼續往下執行到case 9的語句,直到遇到break纔會離開switch。

(默然說話:對了,順便說一下,在Java中,一個整型數除以另一個整型數,最後的結果一定是整型數,所以86/10的商不是8.6,而是8,後面的小數點會被捨棄)

這個程序與多重if的區別,就在於變量quotient的值只會被取一次,而前面多重if語句每一次比較都要從變量score中取值,所以switch在這一點上效率是比較高一點的。
3.2.3 for
在Java中如果要進行重複性指令執行,可以使用for循環。基本語法之一如下:

for(初始值;循環條件;自增量){
    語句(循環體);
}

for循環語法的小括號中,初始值只執行一次,如果是聲明變量,結束for循環時該變量會被銷燬。第一個分號之後的循環條件是一個最後結果是boolean類型的表達式,每次執行循環體語句之前都會被執行一次,如果得到true,纔會繼續執行循環體語句,如果是false,則循環結束。第二個分號後的自增量則是每次循環體語句執行完後都會執行一次。自增量最重要的作用就是讓循環條件不會永久爲真,以免出現死循環。
比如下面的代碼,它能在控制檯上從1顯示到10:

package cn.com.speakermore.ch03;

/**
 *  從1讀到10
 * 文件名:OneToTen.java
 * @author mouyo
 */
public class OneToTen {
    public static void main(String[] args) {
        for(int i=1;i<=10;i++){
            System.out.println(i);
        }
    }
}

這個程序的意思就是i開始爲1,只要i是小於等於10就執行循環體語句(System.out.println(i),意思就是顯示變量i的值),然後i自增1。這是for循環最常見的應用形式。如果for循環體語句只有一條,可以省略大括號,但爲了可讀性與維護性,強烈不建議省略。
九九乘法表常被用於介紹較爲複雜的for循環寫法。如下:

/**
 *  九九乘法表
 * 文件名:NineNineTable.java
 * @author mouyo
 */
public class NineNineTable {
    public static void main(String[] args) {
        for(int i=1;i<10;i++){
            for(int j=1;j<=i;j++){
                System.out.print(i+"*"+j+"="+i*j+"\t");
            }
            System.out.println("");
        }
    }
}

執行結果如下:
九九乘法表
圖3.6 九九乘法表
其實for循環只是將3個複合語句塊寫在一個小括號中而已,第一個語句塊只會執行一次,第二個語句塊專門判斷是否繼續下一次循環,第三個語句塊只是一般的語句塊。
for循環小括號中的語句塊以分號作分隔,而在一個語句塊中如果想寫兩個以上的語句,則使用逗號分隔。有興趣的話,可以研究下面這個九九表的寫法,只使用了一個for循環就完成九九表打印,很逼格哦!不過,基本是看不懂,非常不建議這樣寫:

package cn.com.speakermore.ch03;

/**
 * 高逼格九九乘法表
 * 文件名:NineNineTable2.java
 * @author mouyo
 */
public class NineNineTable2 {
    public static void main(String[] args) {
        for(int i=1,j=1;i<10;j=((j==i)?(++i/i):(j+1))){
            System.out.print(i+"*"+j+"="+i*j+(j==i?'\n':' '));
        }
    }
}

經驗:for循環小括號中第二個語句塊如果沒有寫,默認就是true,所以如果見到如下的循環,表示死循環:


for(;;){
    ……
}

3.2.4 while
while循環語法如下:

while(循環條件){
    循環語句;
}

while循環的執行順序很容易看出來。首先判斷條件是否爲真,若爲真則執行大括號裏的循環語句,然後再次判斷循環條件是否爲真,如此循環,直到循環條件爲假,跳出循環。
while循環比較合適用於循環次數未知的情況,例如,讓用戶輸入學生姓名,直到用戶輸入quit才停止。
下面是一個好無聊的遊戲,不過的確可以說明咱們while循環的特點:

import java.util.Random;

/**
 * 好無聊,不斷生產隨機數,直到出現5爲止
 * @author mouyong
 */
public class RandomStop {
    public static void main(String[] args) {
        while(true){//條件永真,死循環
            int number=new Random().nextInt(10);//產生0-9的隨機數
            System.out.println(number);
            if(number==5){
                System.out.println("總算猜到了5,累死了!");
                break;//break關鍵字,跳出循環
            }
        }
    }
}

某一次執行結果如下:
無聊的遊戲1
圖3.7 無聊的遊戲1
while的條件判斷設置爲true,會造成一直執行循環體,也就是我們通常所說的死循環。new Random().nextInt(10)會隨機產生0-9之間的整數。在while循環中如果執行到break,則會跳出循環。
while循環總是先判斷循環條件,之後纔開始執行循環,所以有可能會出現一開始循環條件爲假,則直接跳過循環語句部分的情況。如果需要先執行一次循環語句,然後再判斷循環條件,則可以使用do…while,它是先執行一次循環語句,然後才進行循環條件的判斷,語法如下:

do{
    循環語句
}while(循環條件);

要注意的一個問題是,while後面是以分號作爲結束的,這個分號是不能寫漏的。上面那個無聊的遊戲也可以使用do…while循環來完成,而且還可以省掉一個if判斷:

import java.util.Random;

/**
 *
 * @author mouyong
 */
public class RandomStop2 {
    public static void main(String[] args) {
        int number;
        do{
            number=new Random().nextInt(10);
        }while(number!=5);
    }
}

某一次執行的結果如下:
無聊的遊戲2
圖3.7 無聊的遊戲2
第一個程序之所以會有兩次判斷,原因就是因爲一開始number的值並沒有產生,所以要先想辦法進入到循環中,而do…while一來就先執行循環語句,產生了number,再判斷要不要執行循環,剛好可以解決這個尷尬的問題。
3.2.5 break、continue
break可以離開當前switch、for、while、do…while的語句塊,並執行後面的語句,在switch中主要用來中斷下一個case的比較,在for、while與do…while中,主要用於中斷當前循環。
continue只作用於循環,switch中不能使用。它不會跳出循環,只會省略之後的循環語句,並回到循環的開頭進行下一次循環,它並不能跳出循環。
下面做個對比,讓大家更加理解break和continue的區別:

/**
 *
 * @author mouyo
 */
public class ContinueAndBreak {
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            if(i==5){
                break;
            }
            System.out.println("i="+i);
        }
    }
}

這段程序會顯示i=1到i=4,因爲在i等於5時就會執行break而離開循環。
循環中使用break
圖3.8 循環中使用break
再看這段程序:

/**
 *
 * @author mouyo
 */
public class ContinueAndBreak {
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            if(i==5){
                continue;
            }
            System.out.println("i="+i);
        }
    }
}

這段程序會顯示除5以外的所有情況,因爲當i=5時,會執行continue直接略過之後的語句,也就是該次的System.out.println()並沒有被執行,直接跳回開頭的i++,並繼續下一次循環,所以i=5沒有被顯示。
循環中使用continue
圖3.9 循環中使用continue

3.3 重點複習

在Java中的基本類型主要可區分爲整數、字節、浮點數、字符與布爾。整數可細分爲short(佔2字節)、int(佔4字節)與long(佔8字節)。byte類型顧名思義,長度就是1字節。浮點數可分爲float(佔4字節)與double(佔8字節)。char類型用來存儲’A’、’B’、’林’等字符符號。在JDK8中,Java的字符采用Unicode6.2.0編碼,JVM採用UTF-16Big Endian,所以每個字符數據類型佔2字節。boolean類型可表示true和false。如果儲存值超出類型範圍,稱爲溢出,會造成程序不可預期的結果。
Java在程序中註釋分爲//單行註釋與/多行註釋/。
數據保存於內存中的位置在程序語言中稱爲變量。對基本類型來說,想要聲明何種類型的變量,就使用相應的類型關鍵字來聲明。變量在命名時有一些規則,它不可以使用數字作爲開頭,也不可以使用一些特殊字符,但變量名不可以與Java關鍵詞同名,也不可以與java保留字同名。
在Java中的命名規範,通常會以小寫字母開始,並在每個單字開始時第一個字母使用大寫,稱爲駝峯命名法。
在方法中聲明的變量稱爲局部變量,不可以聲明局部變量後未初始化之前就使用變量,編譯程序遇到這種情況也會編譯錯誤。
==是由兩個連續的=組成,而不是一個=,=是賦值運算,這一點要注意。
&&與||有所謂的短路運算。因爲與只要其中一個爲假,就可以判定結果爲假,所以對&&來說,只要左操作數爲假,就會直接返回false,不會再去運算右操作數。因爲或只要有一個爲真,結果就是真,所以只要左操作數爲真,就會直接返回true,不會再去運算右操作數。
++和—運算寫在變量前與寫在變量後是有區別的,所以不是特別需要,最好單獨書寫,不要與其他的四則運算混合書寫,以免出現莫名其妙的邏輯錯誤。
在JDK7之後,switch可用於比較整數、字符、字符串與Enum。
for()循環語法的圓括號中,初始化只執行一次,如果變量是在初始化時聲明,則循環結束時就會被銷燬。

3.4 課後練習

3.4.1 選擇題
1. 如果有以下的程序代碼:
int number;
System.out.println(number);
以下描述正確的是()
A.執行時顯示0 B.執行時顯示隨機數字
C.執行時出現錯誤 D.編譯失敗

  1. 如果有以下程序代碼
    System.out.println(10/3);
    以下描述正確的是()
    A.執行時顯示3 B.執行時顯示3.33333333333333
    C.執行時出現錯誤 D.編譯失敗

  2. 如果有如下代碼:
    float radius=88.2;
    double area=2*3.14*radius*radius;
    System.out.println(area);
    以下描述正確的是()
    A.執行時顯示48853.6272 B.執行時顯示48853
    C.執行時出現錯誤 D.編譯失敗

  3. 如果有如下代碼:
    byte a=100;
    byte b=200;
    byte c=(byte)(a+b);
    System.out.println(c);
    以下描述正確的是()
    A.執行時顯示300 B.執行時顯示127
    C.執行時出現錯誤 D.編譯失敗

  4. 如果有如下代碼:
    System.out.println(Integer.MAX_VALUE+1==Integer.MIN_VALUE);
    以下描述正確的是()
    A.執行時顯示true B.執行時顯示false
    C.執行時出現錯誤 D.編譯失敗

  5. 如果有如下代碼:
    System.out.println(-Integer.MAX_VALUE==Integer.MIN_VALUE);
    以下描述正確的是()
    A.執行時顯示true B.執行時顯示false
    C.執行時出現錯誤 D.編譯失敗

  6. 如果有如下代碼:
    int i=10;
    int number=i++;
    number=–I;
    以下描述正確的是()
    A.執行時顯示true B.執行時顯示false
    C.執行時出現錯誤 D.編譯失敗

  7. 如果有如下代碼:
    int i=10;
    int number=++i;
    number=++i;
    以下描述正確的是()
    A.執行後number爲11,i爲11 B.執行後number爲11,i爲12
    C.執行後number爲12,i爲11 D.執行後number爲12,i爲12

  8. 如果有如下代碼:
    for(int i=1;i<10;i++){
    if(i==5){
    continue;
    }
    System.out.println(“i=”+i);
    }
    以下描述正確的是()
    A.顯示i=1到4,以及6到9 B.顯示i=1到9
    C.顯示i=1到4 D.顯示i=6到9

  9. 如果有如下代碼:
    for(int number=0;number!=5;number=new Random().nextInt(10)){
    System.out.println(number);
    }
    以下描述正確的是()
    A.執行時顯示數字永不停止 B.執行時顯示數字0後停止
    C.執行時顯示數字5後停止 D.執行時顯示數字,直到number爲5後停止

3.4.2 操作題
1. 如果有m與n兩個int變量,分別儲存1000與495兩個值,請使用程序算出最大公因子。
2. 在三位的整數中,例如153可以滿足13+53+33=153,這樣的數稱爲水仙花數,試以程序找出所有三位數的水仙花數(據說有4個)

發佈了293 篇原創文章 · 獲贊 56 · 訪問量 72萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章