Thinking in Java-操作符

賦值

“=”,取右邊的值把它復(fù)制給左邊?;绢愋痛鎯?chǔ)了實(shí)際的數(shù)值,而并非指向一個(gè)對象的引用,所以在為其賦值時(shí),是直接將一個(gè)地方的內(nèi)容復(fù)制到了另一個(gè)地方。例如a=b,那么b的內(nèi)容就復(fù)制給a,若接著修改a,那么b不會(huì)受到此影響。但是對象“賦值”的時(shí)候,真正操作的是對對象的引用。若c=d,那么c和d都指向原本d指向的那個(gè)對象。修改c指向?qū)ο蟮膬?nèi)容,也會(huì)影響d。

方法調(diào)用中的別名問題

在許多編程語言中,方法f()似乎要在它的作用域內(nèi)復(fù)制一個(gè)參數(shù)副本,但是實(shí)際上只是傳遞了一個(gè)引用,可能因?yàn)榉椒▍?shù)別名問題引起復(fù)雜的問題。


算數(shù)操作符

Random類的對象如果在創(chuàng)建中沒有傳遞任何參數(shù),則Java會(huì)以當(dāng)前時(shí)間作為隨機(jī)數(shù)生成器的種子,并由此在程序每一次執(zhí)行時(shí)都產(chǎn)生不同的輸出(相同種子生成的隨機(jī)數(shù)序列是相同的)。

一元加、減操作符

一元減號(hào)(-)和一元加號(hào)(+)與二元減號(hào)(-)和二元加號(hào)(+)都是用相同的符號(hào),根據(jù)表達(dá)式的書寫形式,編譯器會(huì)自動(dòng)判斷出使用的是哪一種。

x = -a;
x = a * -b;
x = a * (-b);

一元減號(hào)用于轉(zhuǎn)變數(shù)據(jù)的符號(hào),而一元加號(hào)的唯一作用僅僅是將較小類型的操作數(shù)提成為int


關(guān)系操作符

等于和不到呢關(guān)于適用于所有的基本數(shù)據(jù)類型,而其他比較符不適合boolean類型。

測試對象的等價(jià)性

Integer n1=new Integer(47);
Integer n2=new Integer(47);
n1==n2;

結(jié)果是false,盡管對象的內(nèi)容相同,都為47,然后對象的引用是不同的,而==和!=比較的就是對象的引用。如果想要比較兩個(gè)對象的實(shí)際內(nèi)容是否相同時(shí),必須使用所有對象都適用的特殊方法equals()。但這個(gè)方法不適用于基本類型,基本類型直接使用==和!=即可。

//Value是你自己創(chuàng)建的類
Value v1=new Value();
Value v2=new Value();
v1.equals(v2);

結(jié)果仍然是false,這是由于equals()默認(rèn)的行為是比較引用,除非你在自己的新類中覆蓋equals()方法。大多數(shù)Java類庫都實(shí)現(xiàn)了equals()方法,以便用于比較內(nèi)容而非引用。


邏輯操作符

“與(&&)”、“或(||)”、“非(!)”操作只可應(yīng)用于布爾值。與C和C++不同的是:不可將一個(gè)非布爾值當(dāng)作布爾值在邏輯表達(dá)式中使用,例如1||2這樣是不錯(cuò)誤的。如果在應(yīng)該使用String值的地方使用了布爾值,布爾值會(huì)自動(dòng)轉(zhuǎn)換成適當(dāng)?shù)奈谋拘问剑?code>print()輸出中。浮點(diǎn)數(shù)的比較是非常嚴(yán)格的,即使僅在小數(shù)部分相差非常小的差異,也會(huì)被認(rèn)為是“不相等”的。即使一個(gè)數(shù)只比零大一點(diǎn)點(diǎn),它仍然是“非零”值,如果一定要比較可以設(shè)定一個(gè)非常小的差值,如果判定在差值內(nèi)就近似的認(rèn)為它們是相等的。

float a=1.0;
float b=1.01;
float diff=0.0000001;
if(a-b<diff)
    return true;
return false;

短路

當(dāng)使用邏輯操作符時(shí),會(huì)遇到“短路”現(xiàn)象。因此,整個(gè)邏輯表達(dá)式靠后的部分有可能不會(huì)被運(yùn)算。

if((a=1)>0&&(a=-1)>0&&(a=20)>0);
......
if((a=-5)<0||(a=20)<0);
......

第一個(gè)判斷表達(dá)式中a=1>0為true,此時(shí)a=1,而a=-1>0為false,此時(shí)a=-1,由于&&操作符一旦遇到false,結(jié)果就為false,所以后面的表達(dá)式也不用運(yùn)算了,a的值就等于-1。同理第二個(gè)判斷表達(dá)式中a的值為-5?!岸搪贰庇蓙碚从诖恕?/p>


直接常量

如果編譯器對“直接常量”的類型模棱兩可,則必須對編譯器加以適當(dāng)?shù)?strong>“指導(dǎo)”,用與直接常量相關(guān)的某些字符來額外增加一些信息。

int i=0x2f;  //十六進(jìn)制
int i=0x2F;
int i=0177;  //八進(jìn)制
long l=100L;  //長整型后綴,一般不用l,因?yàn)闀?huì)與1混淆
float f=1f;  //浮點(diǎn)型后綴
double d=2d;  //雙精度浮點(diǎn)型后綴

如果給出的常量超出了char、byte所能表示的最大值,編譯器會(huì)自動(dòng)轉(zhuǎn)換為int型,并給出一個(gè)錯(cuò)誤。如果將比較小的類型傳遞給Integer.toBinaryString()(或Long的靜態(tài)方法),則該類型自動(dòng)被轉(zhuǎn)換為int。

byte b=0x7f;  //long b=0x7f; 編譯器報(bào)錯(cuò)
System.out.println(Integer.toBinaryString(b));   //1111111

指數(shù)計(jì)數(shù)法

在科學(xué)與工程領(lǐng)域,“e”代表自然對數(shù)的基數(shù),約等于2.718(Java中的Math.E給出了更精確的double型的值,Math是java.lang類庫中的,java.lang是程序默認(rèn)加載的一個(gè)類庫)。在Java中看到的e/E代表“10的冪次”。如果編譯器能夠正確識(shí)別類型,如long l=200,就不需要加L,而對于語句float f=1e-43f,編譯器通常會(huì)將指數(shù)作為雙精度數(shù)(double)處理,如果沒有尾隨的f,編譯器會(huì)報(bào)錯(cuò)。


按位操作符

“與(&)”、“或(|)”、“異或(^)”、“非(~)” 操作符用來操作整數(shù)基本數(shù)據(jù)類型中的單個(gè)“比特(bit)”,即二進(jìn)制位。由于“~”是一元操作符所以不能和“=”聯(lián)合使用。我們將布爾值作為一種單比特值對待,可以按位“與”、“或”和異或,但不能按位“非”(大概是為了避免和邏輯上的NOT混淆)。按位操作符不會(huì)造成“短路”。


移位操作符

移位操作符只能處理整數(shù)類型。左移(<<)低位補(bǔ)0,右移(>>)高位補(bǔ)符號(hào)位的值,使用“符號(hào)擴(kuò)展”。無符號(hào)右移(>>>)無論正負(fù)高位都插入0.這是C和C++所沒有的。如果對char、byte或者short類型的數(shù)值進(jìn)行移位處理,那么在移位之前它們會(huì)轉(zhuǎn)換為int類型,得到的結(jié)果也是int類型的值。移位操作符只使用其右操作數(shù)的低5位作為移位長度,這樣防止我們移位超過int型值所具有的位數(shù)。若處理的是long類型的數(shù)值,則只會(huì)用到右操作數(shù)的低6位,防止移位超過long型數(shù)值具有的位數(shù)?!耙莆弧笨膳c“等號(hào)”組合使用。此時(shí)操作符左邊的值會(huì)移動(dòng)指定的位數(shù),然后將結(jié)果賦給左邊的變量。但在進(jìn)行“無符號(hào)”右移時(shí),char、byte或者short值進(jìn)行這樣的運(yùn)算,得到的可能不會(huì)是正確的結(jié)果。它們會(huì)先被轉(zhuǎn)換成int,再進(jìn)行右移操作,然后被截?cái)啵x值給原來的類型。


字符串操作符+和+=

這個(gè)操作符在Java中負(fù)責(zé)連接不同的字符串。C++引入了操作符重載(operator overloading)機(jī)制,可以為幾乎所有操作符增加功能。如果表達(dá)式以一個(gè)字符串起頭,那么后續(xù)所有操作數(shù)都必須是字符串類型(編譯器會(huì)把雙引號(hào)內(nèi)的字符序列自動(dòng)轉(zhuǎn)換為字符串)。

int x=1,y=2,z=3;
String s="x,y,z " +x+y+z;  //第一個(gè)是字符串,后面每一個(gè)操作數(shù)都是字符串,編譯器分別將x、y和z轉(zhuǎn)換為字符串,s為 x,y,z 123
s="x,y,z" +(x+y+z);  //由于第二個(gè)括號(hào)里面不以字符串起頭,所以編譯器執(zhí)行x+y+z后的結(jié)果轉(zhuǎn)換為字符串,s為 x,y,z6
s="x,y,z" +(x+y+z+” d“);  //這個(gè)更為明顯一些,s為 x,y,z6 d
s=(x+" ");  //同上一個(gè),將x的結(jié)果轉(zhuǎn)換為字符串再與后面的字符串拼接,s為1 
s=(""+x);  //以此作為不顯示調(diào)用toString()方法

類型轉(zhuǎn)換操作符

如果執(zhí)行窄型轉(zhuǎn)換(narrowing conversion)的操作,就可能面臨丟失信息的危險(xiǎn)。此時(shí),編譯器會(huì)強(qiáng)制我們進(jìn)行類型轉(zhuǎn)換。而對于擴(kuò)展轉(zhuǎn)換(widening conversion),則不必顯式地進(jìn)行類型轉(zhuǎn)換,因?yàn)樾骂愋涂隙〞?huì)容納原來類型的信息,不會(huì)造成任何信息的丟失。
Java允許我們把任何基本數(shù)據(jù)類型轉(zhuǎn)換成別的基本數(shù)據(jù)類型,但布爾型除外,后者根本不允許任何類型的轉(zhuǎn)換處理?!鳖悺皵?shù)據(jù)類型不允許進(jìn)行類型轉(zhuǎn)換。為了將一種類轉(zhuǎn)換成另一種,必須采用特殊的方法。

截尾和舍入

浮點(diǎn)型轉(zhuǎn)整型時(shí)總是對該數(shù)字進(jìn)行截尾,如果要舍入的話,需要調(diào)用java.lang.Math.round()方法。

提升

如果對基本數(shù)據(jù)類型執(zhí)行算術(shù)運(yùn)算或按位運(yùn)算,只要類型比int小,那么運(yùn)算之前,這些值會(huì)自動(dòng)轉(zhuǎn)換成int。這樣一來,最終生成的結(jié)果就是int類型的。如果想把結(jié)果賦值給較小的類型,就必須使用類型轉(zhuǎn)換。通常表達(dá)式中出現(xiàn)的最大的數(shù)據(jù)類型決定了表達(dá)式最終結(jié)果的數(shù)據(jù)類型。


Java中沒有sizeof

Java不需要sizeof(),因?yàn)樗袛?shù)據(jù)類型在所有機(jī)器中的大小都是相同的,我們不必考慮移植的問題。


優(yōu)先級

優(yōu)先級 操作符 結(jié)合性
1 () , [] , . 左->右
2 ! , +(正) , -(負(fù)) , ~ , ++ , -- 右->左
3 * , / , % 左->右
4 +(加) -(減) 左->右
5 << , >> , >>> 左->右
6 < , <= , > , >= , instanceof 左->右
7 == , != 左->右
8 &(按位與) 左->右
9 ^ 左->右
10 | 左->右
11 && 左->右
12 | | 左->右
13 ? : 右->左
14 = += -= *= /= %= &= | = ^= ~= <<= >>= >>>= 右->左

小結(jié)

能夠?qū)Σ紶栔颠M(jìn)行的運(yùn)算非常有限。我們只能賦予它true和false的值,并測試它是真還是假,而不能將布爾值相加,或?qū)Σ紶栔颠M(jìn)行其他任何運(yùn)算。
在char、byte和short中,對這些的任何一個(gè)進(jìn)行算術(shù)運(yùn)算,都會(huì)獲得一個(gè)int結(jié)果,必須顯式地將其類型轉(zhuǎn)換回原來的類型。但是仍要小心結(jié)果溢出的問題,你不會(huì)從編譯器那里收到出錯(cuò)或警告信息,運(yùn)行時(shí)也不會(huì)出現(xiàn)異常。
對于char、byte或者short,復(fù)合賦值并不需要類型轉(zhuǎn)換。盡管它們執(zhí)行類型提升,但是也會(huì)獲得與直接算術(shù)運(yùn)算相同的結(jié)果。

short a=1;
a=a+1;  //報(bào)錯(cuò),a是short類型的,結(jié)果是int,所以要強(qiáng)制轉(zhuǎn)換a=(short)(a+1)

a+=1;  //通過編譯,原因是因?yàn)閍+=1等價(jià)于a=(short)(a+1),Java對其做了特殊處理
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容