與上一個例子相反,如果我們給出的關於變數x和i的聲明是如下的合法語句:
Java代碼
x = x + i;
但是,它並不是:
Java代碼
x += i;
乍一看,這個謎題可能看起來與前面一個謎題相同。但是請放心,它們並不一樣。這兩個謎題在哪一條語句必是合法的,以及哪一條語句必是不合法的方面,正好相反。
就像前面的謎題一樣,這個謎題也依賴於有關複合賦值操作符的規範中的細節。二者的相似之處就此打住。基於前面的謎題,你可能會想:符合賦值操作符比簡單賦值操作符的限制要少一些。在一般情況下,這是對的,但是有這麼一個領域,在其中簡單賦值操作符會顯得更寬鬆一些。
複合賦值操作符要求兩個運算元都是原始類型的,例如int,或封裝了的原始類型,例如Integer,但是有一個例外:如果在+=操作符左側的運算元是String類型的,那麼它允許右側的運算元是任意類型,在這種情況下,該操作符執行的是字串串連操作。簡單賦值操作符(=)允許其左側的是對象參考型別,這就顯得要寬鬆許多了:你可以使用它們來表示任何你想要表示的內容,只要運算式的右側與左側的變數是賦值相容的即可。
你可以利用這一差異來解決該謎題。要想用 += 操作符來執行字串串連操作,你就必須將左側的變數聲明為String類型。通過使用直接賦值操作符,字串串連的結果可以存放到一個Object類型的變數中。
為了說得具體一些,並提供一個解決方案給這個謎題,假設我們在該謎題的兩個賦值運算式之前有下面這些聲明:
Java代碼
Object x = "Buy ";
String i = "Effective Java!";
簡單賦值是合法的,因為 x + i 是String類型的,而String類型又是與Object賦值相容的:
Java代碼
x = x + i;
複合賦值是非法的,因為左側是一個Object參考型別,而右側是一個String類型:
Java代碼
x += i;
這個謎題對程式員來說幾乎算不上什麼教訓。對語言設計者來說,加法的複合賦值操作符應該在右側是String類型的情況下,允許左側是Object類型。這項修改將根除這個謎題所展示的違背直覺的行為。