第三章:操作符
在底層,在Java中的數據是通過使用操作符來操作的。
3.2 使用Java操作符
操作符接收一個或多個參數,並形成一個新值。參數的形式和普通的方法調用不同,單效果是相同的。使用和其他編程語言相似。
操作符的作用用於操作數,並生成一個新值。另外,有些操作符可能會改變操作數自身的值,這被稱爲副作用。那些能改變其操作數的操作符,最普遍的用途就是用來產生副作用;但要記住,使用此類操作符生成的值,與使用沒有副作用的操作符生成的值,沒有任何區別。
幾乎所有的操作符都只能操作“基本類型”,例外的操作符爲:=,==,!=。這些操作符能操作所有的對象。除此之外,String類支持+和+=。
3.3 優先級
當一個表達式中存在多個操作符時,操作符的優先級就決定了各部分的計算順序。Java對計算順序做了特定的規定。其中,最簡單的規則就是先乘除後加減。程序員經常會忘記其他優先級規則,所以應該用括號()明確規定計算順序。
注意:System.out.println語句中包含+操作符,在這種上下文環境中,+意味着字符串連接,並且如果必要,它還要執行字符串轉換(非String轉String)。
3.4 賦值
賦值使用的操作符時“=”。它的意思是:取右邊的值,把他複製到左邊。右值可以是任何常數,變量,或者表達式。但左值必須是一個明確的,已經命名的變量。也就是說,必須有一個物理空間可以存儲等號右邊的值。
基本數據類型的賦值是很簡單的,基本類型存儲了實際的值,而並非指向一個對象的引用,所以在爲其賦值的時候,是直接將一個地方的內容複製到另一個地方。例如對基本數據類型使用a=b,那麼b的內容複製給a。若接着又修改了a,而b根本不會受這種修改的影響。作爲程序員,這就是大多數情況下我們期望的。
但是爲對象賦值的時候,情況發生了變化。對一個對象進行操作時,我們真正操作的是對對象的引用。所以一個對象賦值另一個對象,將引用從一個地方複製到另一個地方。這種特殊的現象稱爲別名現象,是Java操作對象的一種基本方式,任何避免呢?
t1.level = t2.level
這樣便可以保持兩個對象的彼此獨立,而不是將t1和t2綁定到特定的對象。但你很快就意識到,直接操作對象內的域容易導致混亂,並且,違背了良好的面向對象程序設計原則。這可不是小問題,現在開始大家要注意,爲對象賦值可能會產生意想不到的結果。
方法調用中的別名問題
將一個對象傳遞給方法時,也會產生別名問題。
別名引起的問題,以及解決方法是複雜的話題。需要注意它的存在,並在使用中注意這個陷阱。
3.5 算數操作符
常用的
+
-
*
/
%
擴展,也可以使用+=方式。
一元加,減運算符
一元減符號,用於轉變數據的符號。比如:x = a * (-b)
一元加符號,只是爲了和一元減符號相對應,但是它唯一的作用僅僅是將較小類型的操作數提升爲int。
自增,自減,副作用的操作符。可以出現表達式的前面後者後面。
++,增加一個單位。
--,減少一個單位。
3.6 關係操作符
關係操作符生成一個boolean的結果。它們計算的是操作數的值之間的關係。
<
>
==
!=
擴展,<=等。
對象比較時,一般使用equals方法哦。
3.7 邏輯操作符
與 &&
或 ||
非 !
根據參數的邏輯關係,生成一個boolean結果值。與,或,非只可應用於boolean值。
注意:如果應該使用String的地方使用了boolean值,oolean值會自動轉換成適當的文本形式。
短路
當使用邏輯操作符時,我們會遇到一種短路現象。即一旦能夠明確無誤的確定整個表達式的值,就不在計算表達式餘下的部分。因此,整個表達式靠後的部分可能不會被運算,如:(a || b)時,如果a是真的直接返回true,而不會計算b的值。
直接常量
如果程序裏使用了直接常量,編譯器可以準確的知道要生成什麼樣的類型。但是有時候確實不可行的。如果發生這種情況,必須對編譯器加以適當的“只會“,用於直接量相關的某些字符來額外增加一些信息。比如1L,1F,0x等。後面的是類型。
指數計數法
e,就是那個科學計算的e。
3.8 按位操作符
用來操作整數基本類型中的單個bit,即二進制位。按位操作符會對兩個參數中對應的位執行布爾代數運算,並最終生成一個結果。
&
|
~
3.9 移位操作符
操作的運算對象也是二進制位。只用來處理整數類型。
<<
>>
具體細節忽略。
3.10 三元操作符if-esel
格式:boolean-exp ? value0 : value 1
3.11 字符串操作 +, +=
+,連接不同的字符串。
+=,現獲取原始字符串,然後連接+=後面的部分,然後賦值給表達式左邊的值。
3.12 使用操作符時常見的錯誤
== 和 =的混亂
&& 和 &的混亂
3.13 類型轉換操作符
類型轉換cast的意思是,Java會一種數據類型自動轉換爲另一種。比如:long l = (long)25;
可以爲數值進行類型轉換,也可以爲變量進行類型轉換。注意,這裏可能會引入多餘的轉型。Java中類型轉換是一種安全的操作。然而,如果要執行一種名爲窄化轉換的操作,就可能面臨信息丟失的危險。此時,編譯器會強制我們進行類型轉換。實際上這可是一種危險的事情,無論如何必須顯示的類型轉換。而對於擴展轉換,不必顯示的類型轉換,因爲不會造成信息的丟失。
戴尾和舍入
比如29.8轉int。結果會30還是29?
強制類型轉換時戴尾,如果需要四捨五入是使用java.lang.Math的round方法。
提升
如果對基本數據類型執行算數運算或按位運算,大家會發現,只要類型比int小,那麼在運算之前,這些值會自動轉換爲int。這樣最終生成的結果是int類型。如果把結果賦值給較小的類型,必須做個類型轉換。通常,表達式中出現的最大的數據類型來決定表達式最終的結果類型。
3.14 Java沒有typeOf
在C++中typeOf返回數據項分配的字節數。需要使用typeOf的最大原因就是移植。所以Java不需要這類方法。