2011-10-21 34 views
16

可能重複:
Varying behavior for possible loss of precisionJava打破強大的打字!誰能解釋它?

我發現Java的強類型檢查的不一致在編譯時。 請看下面的代碼:

int sum = 0; 
sum = 1; //is is OK 
sum = 0.56786; //compile error because of precision loss, and strong typing 
sum = sum + 2; //it is OK 
sum += 2; //it is OK 
sum = sum + 0.56787; //compile error again because of automatic conversion into double, and possible precision loss 
sum += 0.56787; //this line is does the same thing as the previous line, but it does not give us a compile error, and javac does not complain about precision loss etc. 

誰能解釋一下?這是已知的錯誤還是期望的行爲? C++給出了一個警告,C#給出了一個編譯錯誤。

Java打破強打字嗎? 您可以將+ =替換爲 - =或* = - 編譯器可以接受一切。

+0

奇怪的是,你是存儲浮在int變量 –

+3

@ KarelFrajtak沒有修飾符的十進制數(如'd'或'f')是雙精度數,而不是浮點數。此外,我想你可能會錯過這一點.. – nfechner

+1

Java在這裏明顯犯了一個錯誤。在允許沉默演員時,他們應該更加精確。而這個原因造成了另一個糟糕的決定。關於integeral類型操作的規範是一團糟。 – irreputable

回答

28

此行爲由語言定義(因此可以)。從the JLS

15.26.2複合賦值運算符

形式E1 OP的化合物賦值表達式= E2相當於 到E1 =(T)((E1)OP(E2)) ,其中T是E1的類型,但E1 僅被評估一次。例如,下面的代碼是正確的:

short x = 3; 
x += 4.6; 

和結果以x具有值7,因爲它是等效於:

short x = 3; 
x = (short)(x + 4.6); 
+4

這是經常被忽視的東西,我們傾向於認爲+ =只是一個較短的版本,但它確實有其他含義。好的提示要記住。 – Ewald

+0

這是不正確的。 java是錯誤的。這個例子沒有理由編譯。 – irreputable

+4

@irreputable - 好吧,這是語言設計師需要做的事情;編譯器符合規範。 – McDowell

5

它編譯因爲編譯器轉換

sum += 0.56787; 

sum = (int)(sum + 0.56787); 
+1

您能否提供指向文檔的鏈接,以解釋此行爲。我認爲正常的行爲是自動轉換成更高精度的類型。 –

+1

演員在加入後執行,而不是之前。看最上面的答案。 –

3

這有沒有關係強類型,但只有與隱式轉換不同的規則。

您正在查看兩個不同的操作員。在第一種情況下,您有簡單的賦值運算符「=」,它不允許將double分配給int。在第二種情況下,您有複合賦值運算符「+ =」,允許將double添加到int,方法是先將double轉換爲int

+0

是的,但這與C++或C#中的工作方式有很大不同。 –

+0

當然,這些是來自JLS的Java特定規則。 –

+1

Eh?根據定義,隱式轉換規則的選擇都是關於強類型與弱類型的關係。 –