通用对象的数组,其中泛型对象的上限与Object不同

时间:2015-01-29 00:24:21

标签: java generics

谁可以解释以下情况中发生的情况?为什么会出错,而另一个不出错?

public class TestClass<T extends Comparable<T>> {
    protected T []items;

    public TestClass(int size, T... values) {
        items = (T[]) new Object[size];
        for (int v = 0; v < Math.min(size, values.length); v++) {
            items[v] = values[v];
        }
    }

    public T getItem() {
        return items[0];
    }

    public static void main(String []args) {
        System.out.println(new TestClass<>(2, 6).getItem()); // Error
    }
}

执行上面的类会出现以下错误:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
    at TestClass.<init>(TestClass.java:5)
    at TestClass.main(TestClass.java:16)
Java Result: 1

有这个:

public class TestClass<T> {
    protected T []items;

    public TestClass(int size, T... values) {
        items = (T[]) new Object[size];
        for (int v = 0; v < Math.min(size, values.length); v++) {
            items[v] = values[v];
        }
    }

    public T getItem() {
        return items[0];
    }

    public static void main(String []args) {
        System.out.println(new TestClass<>(2, 6).getItem()); // Prints 6
    }
}

我还应该提到数组的创建是在超类中完成的,所以我不能改变数组初始化的方式。这也是在Java 8下编译的


我采用的解决方案是这样做: this.items = (T[])new Comparable[size];

只要您不尝试在课堂外使用数组,上述操作才有效。所以这样做是一个错误:

TestClass<Integer> t = new TestClass<>(2, 6);
System.out.println(t.items[0]); // error more ClassCastException

但这样做不是:

System.out.println(new TestClass<>(2, 6).getItem()); // Prints 6

其他人都觉得java泛型类型有点不一致吗?

3 个答案:

答案 0 :(得分:2)

我相信你的问题就在这里

items = (T[]) new Object[size];

类Object []不会扩展Comparable(或任何接口),因此,只是你不能说Comparable c = (Comparable)(new Object()),你也不能将Object []强制转换为Comparable []原来不是一个。

答案 1 :(得分:1)

更新以回应问题中的更改

如果在泛型类型参数上声明了上限,则在调用返回泛型类型的方法或将某些内容分配给泛型类型的变量时,编译器会将强制转换插入到正确的类型中确保类型安全。

在第一种情况下,因为ComparableT的上限,编译器会在构造函数中向Comparable[]插入一个强制转换,因为该数组被赋值为{{1} }}。但是,分配的内容实际上是T[],因此演员表失败了。

在第二种情况下,没有上限,因此编译器不会在构造函数中向Object[]插入强制转换,因此没有强制转换失败。

要使第一个案例成功,即使在泛型类型参数上声明了上限,您也应该遵循How to create a generic array in Java?的建议来创建通用数组。这需要传入Comparable[]对象,以便创建正确类的数组。

Class

答案 2 :(得分:1)

如果(T[]) new Object[size]的{​​{1}}上限为T时你可以Object,那么当T extends Comparable<T>时,类似的事情就是:

(T[]) new Comparable[size]

原因是T被删除到其上限。因此,当T的上限为Object时,强制转换将被删除为强制转换为Object[],这是可以的。但是,当T的上限为Comparable<...>时,强制转换将被删除为强制转换为Comparable[],如果对象的运行时类为Object[],则表示不正常。将其更改为Comparable[]可解决此问题。