請?zhí)峁┮粋€對i的聲明,將下面的循環(huán)轉變?yōu)橐粋€無限循環(huán):
while (i != i + 0) {
}
與前一個謎題不同,你必須在你的答案中不使用浮點數(shù)。換句話說,你不能把i聲明為double或float類型的。
與前一個謎題一樣,這個謎題初看起來是不可能實現(xiàn)的。畢竟,一個數(shù)字總是等于它自身加上0,你被禁止使用浮點數(shù),因此不能使用NaN,而在整數(shù)類型中沒有NaN的等價物。那么,你能給出什么呢?
我們必然可以得出這樣的結論,即i的類型必須是非數(shù)值類型的,并且這其中存在著解謎方案。的 + 操作符有定義的非數(shù)值類型就是String。+ 操作符被重載了:對于String類型,它執(zhí)行的不是加法而是字符串連接。如果在連接中的某個操作數(shù)具有非String的類型,那么這個操作書就會在連接之前轉換成字符串[JLS 15.18.1]。
事實上,i可以被初始化為任何值,只要它是String類型的即可,例如:
String i = "Buy seventeen copies of Effective Java";
int類型的數(shù)值0被轉換成String類型的數(shù)值”0”,并且被追加到了感嘆號之后,所產(chǎn)生的字符串在用equals方法計算時就不等于最初的字符串了,這樣它們在使用==操作符進行計算時,當然就不是相等的。因此,計算布爾表達式(i != i + 0)得到的值就是true,循環(huán)也就永遠不會被終止了。
總之,操作符重載是很容易令人誤解的。在本謎題中的加號看起來是表示一個加法,但是通過為變量i選擇合適的類型,即String,我們讓它執(zhí)行了字符串連接操作。甚至是因為變量被命名為i,都使得本謎題更加容易令人誤解,因為i通常被當作整型變量名而被保留的。對于程序的可讀性來說,好的變量名、方法名和類名至少與好的注釋同等重要。
對語言設計者的教訓與謎題11和13中的教訓相同。操作符重載是很容易引起混亂的,也許 + 操作符就不應該被重載用來進行字符串連接操作。有充分的理由證明提供一個字符串連接操作符是多么必要,但是它不應該是 + 。
while (i != i + 0) {
}
與前一個謎題不同,你必須在你的答案中不使用浮點數(shù)。換句話說,你不能把i聲明為double或float類型的。
與前一個謎題一樣,這個謎題初看起來是不可能實現(xiàn)的。畢竟,一個數(shù)字總是等于它自身加上0,你被禁止使用浮點數(shù),因此不能使用NaN,而在整數(shù)類型中沒有NaN的等價物。那么,你能給出什么呢?
我們必然可以得出這樣的結論,即i的類型必須是非數(shù)值類型的,并且這其中存在著解謎方案。的 + 操作符有定義的非數(shù)值類型就是String。+ 操作符被重載了:對于String類型,它執(zhí)行的不是加法而是字符串連接。如果在連接中的某個操作數(shù)具有非String的類型,那么這個操作書就會在連接之前轉換成字符串[JLS 15.18.1]。
事實上,i可以被初始化為任何值,只要它是String類型的即可,例如:
String i = "Buy seventeen copies of Effective Java";
int類型的數(shù)值0被轉換成String類型的數(shù)值”0”,并且被追加到了感嘆號之后,所產(chǎn)生的字符串在用equals方法計算時就不等于最初的字符串了,這樣它們在使用==操作符進行計算時,當然就不是相等的。因此,計算布爾表達式(i != i + 0)得到的值就是true,循環(huán)也就永遠不會被終止了。
總之,操作符重載是很容易令人誤解的。在本謎題中的加號看起來是表示一個加法,但是通過為變量i選擇合適的類型,即String,我們讓它執(zhí)行了字符串連接操作。甚至是因為變量被命名為i,都使得本謎題更加容易令人誤解,因為i通常被當作整型變量名而被保留的。對于程序的可讀性來說,好的變量名、方法名和類名至少與好的注釋同等重要。
對語言設計者的教訓與謎題11和13中的教訓相同。操作符重載是很容易引起混亂的,也許 + 操作符就不應該被重載用來進行字符串連接操作。有充分的理由證明提供一個字符串連接操作符是多么必要,但是它不應該是 + 。