[英]Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)
[英]Why doesn't compound assignment in Java catch overflow problems?
令我震驚的是,以下代碼將在沒有警告的情況下編譯:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value += increment;
}
雖然這會產生編譯時錯誤,正如您所期望的那樣:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value = value + increment;
}
我檢查了一下,事實上,JLS(第15.26.2節)有這樣的說法:
形式E1 op = E2的復合賦值表達式等效於E1 =(T)((E1)op(E2)),其中T是E1的類型,除了E1僅被評估一次。
這對我來說似乎很荒謬。 為什么他們覺得有必要在這里明確投射? 似乎自動類型轉換無論如何都會處理擴展,並且像這樣自動縮小幾乎可以保證導致整數溢出。
這是一個解釋:
當你執行一個賦值(第一個代碼片段)時,java強制執行類型檢查,因為LHS和RHS很可能彼此獨立。
但復合運算符更像是增量運算符。 + =修改所涉及變量的值,而不是為變量賦值。 修改字節時,您希望得到一個字節作為結果。 為了簡化生活,java為復合運算符執行隱式類型轉換,因為它們是修飾符。
復合賦值運算符由JLS( 15.26.2 )指定如下:
“
E1 op= E2
形式的復合賦值表達式相當於
E1 = (T)((E1) op (E2))`,
其中T是E1的類型,但E1僅被評估一次。“
在這種情況下,E1的類型為int
E2的類型為long
,op為+
。 所以這相當於:
value = (int)(value + increment);
添加一個int
和一個long
會給出一個long
,然后在賦值之前將其int
轉換為int
。 這一切都很好,因此沒有編譯錯誤。
這與簡單賦值(即value = value + increment;
)之間的區別在於簡單賦值沒有類型轉換。
好的, 為什么他們這樣定義呢?
我認為原因是做這樣的例子:
byte b = ...
b += 1;
如果沒有類型轉換, b += 1
將是編譯錯誤,您需要將其寫為:
b += (byte) 1;
此鏈接分析了您提出的問題。
為避免令人不快的意外,請不要對byte,short或char類型的變量使用復合賦值運算符。 在int類型的變量上使用復合賦值運算符時,請確保右側的表達式不是long,float或double類型。 在float類型的變量上使用復合賦值運算符時,請確保右側的表達式不是double類型。 這些規則足以防止編譯器生成危險的縮小轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.