谜题9:半斤
現在該輪到你來寫些代碼了,好消息是,你只需為這個謎題編寫兩行代碼,并為下一個謎題也編寫兩行代碼。這有什么難的呢?我們給出一個對變量x和i的聲明即可,它肯定是一個合法的語句:
x += i;但是,它并不是:
x = x + i;許多程序員都會認為該迷題中的第一個表達式(x += i)只是第二個表達式(x = x + i)的簡寫方式。但是這并不十分準確。這兩個表達式都被稱為賦值表達式。第二條語句使用的是簡單賦值操作符(=),而第一條語句使用的是復合賦值操作符。(復合賦值操作符包括 +=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=和|=)Java語言規范中講到,復合賦值 E1 op= E2等價于簡單賦值E1 = (T)((E1)op(E2)),其中T是E1的類型,除非E1只被計算一次。
換句話說,復合賦值表達式自動地將它們所執行的計算的結果轉型為其左側變量的類型。如果結果的類型與該變量的類型相同,那么這個轉型不會造成任何影響。然而,如果結果的類型比該變量的類型要寬,那么復合賦值操作符將悄悄地執行一個窄化原始類型轉換。因此,我們有很好的理由去解釋為什么在嘗試著執行等價的簡單賦值可能會產生一個編譯錯誤。
為了說得具體一些,并提供一個解決方案給這個謎題,假設我們在該謎題的兩個賦值表達式之前有下面這些聲明:
short x = 0;int i = 123456;復合賦值編譯將不會產生任何錯誤:
x += i; // 包含了一個隱藏的轉型!你可能期望x的值在這條語句執行之后是123,456,但是并非如此l,它的值是-7,616。int類型的數值123456對于short來說太大了。自動產生的轉型悄悄地把int數值的高兩位給截掉了。這也許就不是你想要的了。
相對應的簡單賦值是非法的,因為它試圖將int數值賦值給short變量,它需要一個顯式的轉型:
x = x + i; // 不要編譯——“可能會丟掉精度”這應該是明顯的,復合賦值表達式可能是很危險的。為了避免這種令人不快的突襲,請不要將復合賦值操作符作用于byte、short或char類型的變量上。在將復合賦值操作符作用于int類型的變量上時,要確保表達式右側不是long、float或double類型。在將復合賦值操作符作用于float類型的變量上時,要確保表達式右側不是double類型。這些規則足以防止編譯器產生危險的窄化轉型。
總之,復合賦值操作符會悄悄地產生一個轉型。如果計算結果的類型寬于變量的類型,那么所產生的轉型就是一個危險的窄化轉型。這樣的轉型可能會悄悄地丟棄掉精度或數量值。對語言設計者來說,也許讓復合賦值操作符產生一個不可見的轉型本身就是一個錯誤;對于在復合賦值中的變量類型比計算結果窄的情況,也許應該讓其非法才對。
轉載于:https://www.cnblogs.com/yuyu666/p/9840361.html
總結
- 上一篇: [leetcode] 62 Unique
- 下一篇: 网络对抗技术实验3