2013-05-13 15 views
6

我最近發現,數組是通過Java實現的。也就是說,他們只在運行時才知道類型信息。但我對這個定義有點困惑。數組在Java中被實現

如果說數組只在運行時才知道類型信息,我應該從字面上能夠將任何值賦給任何數組,因爲只有在運行時才知道類型錯誤,所以只會在運行時拋出錯誤。但實時情況並非如此。我們得到了編譯時錯誤。

那麼有人可以拋出「這是什麼意思 - 數組是真實的」?

+0

你說的是「通用數組」嗎? – Sam 2013-05-13 09:18:43

+0

@Sam:是的。我認爲所有的陣列都是通用的。不是嗎?從你的問題看來,只有通用數組才被通用化! – shar 2013-05-13 09:20:29

+0

是的,原因是'代碼遺產',這意味着保持它與非通用代碼兼容。我相信它被稱爲「類型擦除」。 – Sam 2013-05-13 09:23:02

回答

7

我認爲這意味着,代碼定線將拋出一個異常:

String[] arrayOfStrings = new String[10]; 
Object[] arrayOfObjects = arrayOfStrings; // compiles fine 
arrayOfObjects[0] = new Integer(2); // throws a runtime exception (ArrayStoreException IIRC) 

數組是協變:字符串[]擴展對象[]。但是數組的實際類型在運行時是已知的,並且嘗試存儲不正確類型的實例會引發異常。

4

我相信你要找的術語是reifiable

由於在運行時類型擦除,可重寫類型不會丟失任何類型信息。 reifiable類型的實例包括:

  • 原語
  • 非通用引用類型
  • 陣列或基元或陣列非通用引用類型的 。

Reifiable並不意味着在編譯時不知道類型。什麼這是否意味着是類似於以下,無法鍵入檢查:

List<Integer>[] myList; 

陣列攜帶它們存儲類型的運行時信息。無法在運行時檢查不可反轉的類型,這不會使它們成爲陣列組件類型的良好候選項。

當使用reifiable類型作爲組件類型的數組,例如String[]完整的類型信息是在運行時可用的,所以類型檢查可以進行。

String[] someArray = new String[2]; 
//some factory returns Integer upcasted to Object 
someArray[0] = someFactory.getType("Integer"); //throws RuntimeException 

來源:

http://docs.oracle.com/javase/tutorial/java/generics/nonReifiableVarargsType.html http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ106(良好)

+0

如果在編譯時知道類型,那麼請考慮JB Nizet提供的這個問題的答案。在這個例子中,我們得到了一個運行時異常(ArrayStoreException)。他們爲什麼不在運行時間本身檢查?如果問題太天真,我很抱歉。 – shar 2013-05-13 09:36:15

+0

@shar您的權利,我在評論中標記爲異常錯誤,我剛剛注意到這一點。工廠的例子只是試圖說明由於代碼的動態特性而導致無法在編譯時處理的ArrayStoreException。 – 2013-05-13 09:51:04

3

如果說只知道在運行時類型信息陣列,我應該從字面上可以任意值分配給任何陣列,因爲只有在運行時才知道類型輸入,所以只在運行時拋出錯誤。但實時情況並非如此。我們得到了編譯時錯誤。

Reifiable類型知道在運行時編譯時它們的類型,這就是爲什麼編譯器仍然會阻止你做出愚蠢的錯誤在那裏可以(這是什麼在讓他們過點?)

然而,有次當編譯器不能總是制定出一定的分配(例如)是否將是有效的,因爲它不知道確切的類型,而這正是物化類型可以檢查。例如:

Object[] arr = new String[5]; 
arr[0] = 7; 

...這將編譯,因爲在第二行的編譯器只知道靜態類型的數組作爲Object的,而動態類型更具體的東西。它在運行時會失敗,它只能這樣做,因爲(與泛型集合類不同)特定類型在運行時是已知的。

1

doc提到:

甲reifiable類型是類型,其類型的信息是在運行時完全可用 。這包括基元,非泛型類型,原始類型, 和未綁定通配符的調用。

不可否定類型是類型,其中通過類型擦除在 編譯時已刪除信息 - 通用類型的調用 未定義爲無界通配符。一個不可確定的類型在運行時沒有可用的所有信息。不可確定的 類型的示例是List和List; JVM不能在運行時告訴這些類型之間的差異。如泛型的限制條件所示,在某些情況下,無法使用不可確定類型 :例如,在表達式的一個實例中,或者在數組中的某個元素爲 。

因此,數組是具體化和協變的,但泛型是不變的,並且被自然類型擦除。如果未添加正確類型的元素,則數組提供運行時類型安全並拋出ArrayStore異常。