- 論壇徽章:
- 0
|
java解惑學(xué)習(xí)筆記3:
謎題7:互換內(nèi)容
public class CleverSwap{
public static void main(String[] args){
int x = 1984; // (0x7c0)
int y = 2001; // (0x7d1)
x^= y^= x^= y;
System.out.println("x= " + x + "; y= " + y);
}
}
它會打印出什么呢?
x = 0111 1100 0000 ,y = 0111 1101 0001 x^=y,后 x = 0000 0001 0001
y^=x 后y = 0111 1100 0000 x^=y 后 x = 0111 1101 0001
所以 x = 0x7d1 y = 0x7c0
很好嘛!不用中間變量的swap方法。但是打印的結(jié)果出乎意料:x = 0; y = 1984
郁悶?zāi)模?br />
Java語言規(guī)范描述到:操作符的操作數(shù)是從左向右求值的。為了求表達(dá)式 x ^= expr的值,
x的值是在計算expr之前被提取的,并且這兩個值的異或結(jié)果被賦給變量x。在CleverSwap程序中,
變量x的值被提取了兩次——每次在表達(dá)式中出現(xiàn)時都提取一次——但是兩次提取都發(fā)生在所有的
賦值操作之前。
按編譯時引入中間變量的方法來分解x^= y^= x^= y,
x = x ^(y^x^y) : x與y兩次xor, 結(jié)果還是x ,x xor x ,結(jié)果是0 ,故最終得0;
int tmp1 = x ; // x在表達(dá)式中第一次出現(xiàn)
int tmp2 = y ; // y的第一次出現(xiàn)
int tmp3 = x ^ y ; // 計算x ^ y
x = tmp3 ; // 最后一個賦值:存儲x ^ y 到 x
y = tmp2 ^ tmp3 ; // 第二個賦值:存儲最初的x值到y(tǒng)中
x = tmp1 ^ y ; // 第一個賦值:存儲0到x中
solution:
丑陋而又無用的解法:
y = (x^= (y^= x))^ y
最好的方法是不要這么干!不想使用中間變量我們可以這樣:{a = a + b; b = a - b;a = a - b};
謎題8:Dos Equis
public class DosEquis{
public static void main(String[] args){
char x = 'X';
int i = 0;
System.out.println(true ? x : 0);
System.out.println(false ? i : x);
}
}
和我一樣性子急的人,看到這個問題就忍不住想說:
結(jié)果是 XX
很不幸,我們又被騙了,當(dāng)表達(dá)式是復(fù)合類型的時候,事情往往沒那么簡單,
表達(dá)式結(jié)果的類型有時候讓我覺得自己被玩了,讓我們找出躲在陰暗的角落表達(dá)式規(guī)范,來增加對自己
代碼的掌控能力。
確定條件表達(dá)式結(jié)果類型的規(guī)則的核心:
1.如果第二個和第三個操作數(shù)具有相同的類型,那么它就是條件表達(dá)式的類型。換句話說,
你可以通過繞過混合類型的計算來避免大麻煩。
2.如果一個操作數(shù)的類型是T(byte,short,char),而另一個操作數(shù)是一個int類型的常量表達(dá)式,
它的值是可以用類型T表示的,那么條件表達(dá)式的類型就是T。
3.否則,將對操作數(shù)類型運(yùn)用二進(jìn)制數(shù)字提升,而條件表達(dá)式的類型就是第二個和第三個操作數(shù)被提升之后的類型。
對于第一個輸出,兩個操作數(shù)是char和int型常量,采用規(guī)則2,輸出是char型X,
對于第二個輸出,采用規(guī)則3,其返回的類型是對int和char運(yùn)用了二進(jìn)制數(shù)字提升之后的類型,即int。
表達(dá)式的結(jié)果決定那一個重載print method 被調(diào)用,對第一個表達(dá)式來說,PrintStream.print(char)將被調(diào)用,而對第二個表達(dá)式來說,
PrintStream.print(int)將被調(diào)用。前一個重載方法將變量x的值作為Unicode字符(X)來打印,而后一個重載方法將其作為一個十進(jìn)制整數(shù)
(88)來打印。
所以最終的結(jié)果是 X88
經(jīng)驗(yàn):總之,通常最好是在條件表達(dá)式中使用類型相同的第二和第三操作數(shù)。否則,你和你的程序的讀者必須要徹底理解這些表達(dá)式行為的復(fù)雜規(guī)范。
本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u/28187/showart_242719.html |
|