2013-04-20 27 views
106

我注意到Java SE 6和Java SE 7之間的自動拆箱行爲有所不同。我想知道爲什麼這樣,因爲我找不到任何更改文檔在這兩個版本之間的行爲中。Java 6與Java 7之間的自動拆箱差異

這裏有一個簡單的例子:

Object[] objs = new Object[2]; 
objs[0] = new Integer(5); 
int myInt = (int)objs[0]; 

編譯沒有從的Java SE 7的javac不過,如果我給編譯器的「-source 1.6」的說法,我得到的最後一行的錯誤:

inconvertible types 
found : java.lang.Object 
required: int 

我嘗試下載Java SE 6以使用原生版本6編譯器(沒有任何-source選項)進行編譯。它同意並給出與上述相同的錯誤。

那麼是什麼給?從更多的實驗看來,Java 6中的拆箱似乎只能清除(在編譯時)清空盒裝類型的值。舉例來說,這部作品在兩個版本:

Integer[] objs = new Integer[2]; 
objs[0] = new Integer(5); 
int myInt = (int)objs[0]; 

如此看來,Java的6和7之間,拆箱功能得到加強,以便能夠一舉投和拆箱的對象類型,不知道(在編譯時)該值是正確的盒裝類型。然而,通過閱讀Java語言規範或Java 7發佈時編寫的博客文章,我看不到任何這種變化,所以我想知道變化是什麼以及這個「特性」被稱爲什麼?

只是好奇:由於變化,有可能引發「錯誤」 unboxings:

Object[] objs = new Float[2]; 
objs[0] = new Float(5); 
int myInt = (int)objs[0]; 

編譯沒有問題,但給在運行時一個ClassCastException。

對此有何參考?

+17

有趣。自動裝箱混亂的新成分。我認爲你的例子可以用一個單一的對象而不是一個數組更簡單和清晰。 Integer obj = new Integer(2); int x =(int)obj;':在Java 7上工作,在Java 6上給出錯誤。 – leonbloy 2013-04-20 12:15:55

+1

您正在使用哪個JDK?它可能也必須與不同的供應商... – 2013-04-20 12:48:04

+1

@leonbloy:關於簡化的好處,我做了一些簡化(從我的原始代碼),但不知何故停了太早! – Morty 2013-04-20 15:20:52

回答

91

它看起來像在section 5.5 Casting Conversion of Java 7 JLS相比進行了更新,the same section in the Java 5/6 JLS語言,大概澄清允許的轉換。

爪哇7 JLS說

引用類型的表達式可以經受鑄造轉換到基本類型,沒有錯誤,通過取消裝箱轉換。

爪哇5/6:

引用類型的值可以通過解包轉換被轉換爲基本類型(§5.1.8)。

Java 7 JLS還包含從引用類型到基元的允許轉換(此表不包含在Java 5/6 JLS中)的表(表5.1)。這明確列出了從Object轉換爲基元的轉換,並將其作爲縮小的參考轉換進行拆箱。

的原因是this email解釋說:

底線:如果規範。允許(Object)(int)它也必須允許(int)(Object)。

+10

+ 1去核心(JLS)。 – 2013-04-20 14:07:53

35

你是對的;更簡單地說:

Object o = new Integer(1234); 
int x = (int) o; 

這在Java 7中起作用,但在Java 6及更低版本中出現編譯錯誤。奇怪的是,這個功能沒有明顯的記錄;例如,它沒有提到here。如果它是一個新功能或錯誤修復(或者一個新的錯誤?),這是值得商榷的,請參閱related info and discussion。一致意見似乎指向原始規範中的ambiguity,這導致在Java 5/6上稍微不正確/不一致的實現,該實現在7中得到修復,因爲它對實現JSR 292(動態類型化語言)至關重要。

Java自動裝箱現在有更多的陷阱和驚喜。例如

Object obj = new Integer(1234); 
long x = (long)obj; 

將編譯,但在運行時失敗(並ClassCastException)。這一點,而是將工作:

long x = (long)(int)obj;

+2

感謝您的回答。但是,有一件事我不明白。這是對JLS及其附帶實現(參見郵件討論)的澄清,但爲何要在JVM上適應其他類型的語言?畢竟,這是語言的變化,而不是虛擬機:虛擬機的轉換行爲與以往一樣,編譯器使用現有的機制來實現此功能,以轉換爲整數並調用.intValue()。那麼,如何在Java語言中正確地進行這種改變,有助於在VM上運行其他語言?我同意你的鏈接暗示這一點,只是想知道。 – Morty 2013-04-22 17:46:45

+2

@Morty:擊敗我 – leonbloy 2013-04-22 18:00:55