为什么Java允许类型不安全的阵列分配?

Raf*_*l T 15 java arrays runtime-error declaration type-safety

通常,Java可以被视为类型安全的语言.我知道泛型有一些缺陷,但我最近遇到了一个前所未有的问题.要打破它:

Object[] objects = new Integer[10];
objects[0] = "Hello World";
Run Code Online (Sandbox Code Playgroud)

不会导致预期的编译时错误.我会假设一个数组的声明Object将不允许指向一个其他的数组.在泛型中,我不允许做出如下奇怪的事情:

ArrayList<Object> objs = new ArrayList<Integer>
Run Code Online (Sandbox Code Playgroud)

如果我试图欺骗Java做一些事情

ArrayList<? extends Object> objects = new ArrayList<Integer>
Run Code Online (Sandbox Code Playgroud)

我被允许声明它,但我只能添加类型的对象null.

为什么Java不会阻止声明这样的weired数组呢?

Ste*_*n C 12

首先,我应该指出这是类型安全的.

Object[] objects = new Integer[10];
objects[0] = "Hello World";
Run Code Online (Sandbox Code Playgroud)

因为会抛出异常.(它不是静态类型安全的......但这完全是另一种说法.)

Java允许这一点的原因是历史性的.在Java 5之前,Java不支持任何形式的泛型.Gosling说,如果他们有时间弄清楚并将泛型纳入Java 1.0,他们就会这样做.

不幸的是,他们没有.但他们仍然希望能够使用以下签名编写类似通用排序方法的内容:

    void sort(Object[] array, Comparator comp) ...
Run Code Online (Sandbox Code Playgroud)

为了使这个方法适用于任何类型的对象数组(没有泛型),有必要使数组协变; 即,使形式传递String[]Integer[]作为正式类型的参数是合法的Object[].如果他们没有这样做,你将不得不将其复制String[]到a Object[],对其进行排序,然后将其复制回来.

  • @RafaelT:关键是你不应该创建一个单独的`void sort(Apple []数组,AppleComparator comp)`,`void sort(Car []数组,CarComparator comp)`等,它们都有除签名外的相同源代码.这并不意味着所有比较器都与所有阵列兼容,只是类型检查必须在运行时进行.(随着泛型的出现,我们可以编写`<T> void sort(T []数组,Comparator <T> comp)`并获得编译时类型检查,但语言直到Java才提供5.) (3认同)

mil*_*ose 7

除了"传统设计"之外,我认为没有答案.(我承认这是一种说"因为"的奇特方式.)你几乎需要能够以某种方式完成相应的最后作业.(否则你会坚持使用手动上/下模型制作大量的副本,假设Java 1.4的语言特性)

在Java 1中,当数组的类型语义基本上是一成不变的时候,泛型不可用,或者甚至还需要考虑很长时间.所以没有可用的机制来表达使这个构造类型安全所需的高阶类型约束 - 而Gosling(IIRC是一个简单的粉丝)觉得解决编译时类型安全的边缘情况并不值得复杂的语言无论有哪种解决方案.或者没有在运行时进行足够的检查以寻找解决方案.(在一天结束时,语言设计决策至少在某种程度上是任意的,并且只有一个人可以肯定地回答这个问题.)