2013-05-13 14 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异常。