3: Controlling Program Flow(控制程序流程)

使用Java運算符
幾乎所有的運算符都只能作用于primitive。但是‘=’,‘==’,以及‘!=’是例外,它們可以作用于任何對象(由此也是對象方面一個很讓人頭暈的問題。)此外,String類也支持‘+’和‘+=’。
優先級
賦值

primitive賦值的時候,是將內容從一個地方直接拷貝到另一個地方。
操控對象就得通過reference來進行操作。當你“在對象之間”進行賦值得時候,實際上你是在拷貝它得reference。
方法調用期間的aliasing
數學運算符
正則表達式(Regular expressions)
單元的加號和減號運算符
自動遞增與遞減
對于前置遞增和前置遞減,(也就是++a和--a),操作過程是會先計算再返回。對于后置遞增和后置遞減,(也就是a++和a--),操作步驟是先返回再計算。
關系運算符
測試對象的相等性

==和!=比較的是對象的reference。要想比較這兩個對象的實際內容,必須使用每個類都有的,專門的equals()方法(primitives沒有,因為==和!=就用得很好)。
equals()的缺省行為是比較reference。
邏輯運算符
短接
位運算符

位運算符可以與=連起來用,以表示同時進行計算和賦值:&=,|=和^=都是合法的。(至于~,它既然是一個單元運算符,也就不需要同=綁在一起了。)
Boolean類型會被當作只有一位的值,所以它多少有點不同。你可以進行與,或,以及異或運算,但是不能進行非運算(可能是為了防止同邏輯非相混淆)。對于boolean,位運算用邏輯運算的在功能上是相同的,只是它沒有短接。此外boolean的位運算里有一個邏輯運算所沒有的異或。
移位運算符
它只能用于整數型的primitive數據。
三元if-else運算符
逗號運算符
Java里面,唯一一個把逗號當運算符用的地方是for循環。
String的+運算符
常見的使用運算符方面的錯誤
類型轉換運算符

碰到所謂的narrowing conversion的時候(也就是說,當你將一個能保存較多信息的數據類型,轉換成一個保存不了這么多信息的數據類型時),它會產生一個異常。編譯器會強制你明確地進行轉換,實際上它的潛臺詞是“這么做可能很危險——如果你一定要做,那么請明確地告訴我”。
對于widening conversion,就不必進行顯式轉換了,因為新類型可以存儲比舊類型更多的信息,所以什么都丟不了。
Java允許你對除boolean之外的其它primitive類型的數據進行任意的轉換,而boolean則根本不能轉換。
類是不允許轉換的。要讓他們相互轉換,必須要有特殊的方法。(String是一個特例。此外,所有對象都可以在它的類系(family of types)里面上下傳遞。)
常量(Literals)
C,C++或者Java里面都沒有兩進制常量值的表示方法。
跟在常量值后面的那個數字表明了它的類型。大寫或者小寫的L表示long,大寫或者小寫的F表示float,而大寫或者小寫的D表示double。
編譯器通常會把用指數表示的數字當成double,所以在給float賦值如果沒有后綴的f的話,它就會給你一個錯誤信息,告訴你你必須將double轉換成float。
提升
Java沒有“sizeof”
重訪優先級
Ulcer Addicts Really Like C A lot.

Mnemonic

Operator type

Operators

Ulcer

Unary

+ - ++--

Addicts

Arithmetic(and shift)

* / % + - << >>

Really

Relational

> < >= <= == !=

Like

Logical(and bitwise)

&& || & | ^

C

Conditional(ternary)

A > B? X: Y

A Lot

Assignment

=(and compound assignment like *=)

運算符的總結
boolean的限制性是很強的。你只能賦給它true和false這兩個值,而且只能測試它的真或假,你不能把boolean值加起來,或者進行其它什么操作。
進行數學運算的時候,char,byte,以及short,都會先進行提升,而運算結果也是int,因此如果想把它賦還給原先那個變量的話,舊必須明確地進行類型轉換(屬于會丟失信息的narrowing conversion)。

執行控制
true和false
if-else
return
循環語句
do-while
while與do-while的唯一區別就是,即使第一次判斷的結果是false,do-while的statement也會至少運行一次。
for
for循環通常被用于“計數”的任務。
你可以在for語句里定義多個變量,但必須是相同類型的。
只有for語句才有在“控制表達式”里定義變量的能力。千萬別在其它選擇語句或循環語句里這么做。
逗號運算符
break和continue

break會忽略尚未執行的循環代碼,并且退出循環。
continue會跳過尚未執行的代碼,中斷本次循環,再進入下一周期的循環。
臭名昭著的“goto”
在Java里,唯一能放標簽的地方,就是在循環語句的外面。而且必須直接放——循環語句和標簽之間不能有任何東西。而這么做的唯一理由就是,你會嵌套多層循環或選擇。因為通常情況下break和continue關鍵詞只會中斷當前循環,而用了標簽之后,它就會退到label所在的地方。
1. 普通的continue會退到內部循環的最開始,然后繼續執行內部循環。
2. 帶標簽的continue會跳轉到標簽,并且重新進入直接跟在標簽后面的循環。
3. break會從循環的“底部溜出去”。
4. 帶標簽的break會從由這個標簽標識的循環的“底部溜出去”。
在Java里,能讓你使用標簽的唯一理由就是,在嵌套循環的同時還要用break和continue退出多層循環。
switch
在case語句里,單引號括起來的字符在用于比較的時候,會返回整數值。
計算細節
將float或double轉換成整數的時候,它總是將其后面的小數截去。
Math.random()會生成0.0,或者用數學術語,它的值域是[0,1)。

總結

練習

「讀書筆記」Thinking in Java 3rd Edition - 4: Initialization & Cleanup