Java初始化通用数组

时间:2015-09-17 13:05:21

标签: java generics

Paragraph

T有一个约束,它实现了Comparable。上面的行失败并带有异常

  T[] genericArray= (T[])(new Object[2]);

如何初始化T有约束的通用数组?

2 个答案:

答案 0 :(得分:3)

Object未实现Comparable

而不是将其创建为Object[],而不是将其创建为Comparable[]

与您的评论相关:

可以声明任何类型的变量。创建数组时,您不是在数组中创建对象,而是仅分配内存来存储对象的引用。

所以你可以写:

Comparable x = "Pippo"; // Because String is Comparable

你也可以写

Comparable[] x = new Comparable[1];
x[0] = "Pippo";    // Here you add a concrete String that is a
                   // Comparable type on the first position

答案 1 :(得分:1)

您收到此错误是因为Object未实现Comparable,因此Object[]不是Comparable[]的子类型(因为类型擦除,它是genericArray的运行时类型。

潜在的问题是你想要创建一个通用数组。 这在Java中是不可能的。原因是,与泛型不同,数组元素的类型在运行时是已知的。如果编写new T[],则不知道必须创建哪种类型的数组。

你试图通过创建一些超类型的数组来绕过这个。但这也是不正确的(如果你这样做,你应该收到警告)。如果您创建一个包含new Comparable[size]的数组,则会创建一个Comparable s数组,而不是某个子类型为Comparable的数组。 T[]可能是String[]Long[]String[]Long[]的类型不同于Comparable[](也是在运行时)。< / p>

要演示此问题,请考虑以下程序:

public class Foo<T extends Comparable> {    
    T[] createArray() {
        return (T[])new Comparable[1];
    }

    public static void main(String... args) {
        Foo<String> foo = new Foo<>();
        String[] ss = foo.createArray(); // here
    }
}

第一眼看上去可能看起来很不错,但是当你运行它时,你得到一个ClassCastException,因为在标记的行中Object[]被强制转换为String[]

解决方案是使用Class<T>个对象作为所谓的类型标记。这些允许您存储类型,以便您可以在运行时访问它。现在,您可以使用Array.newInstance(Class<T>, int...)创建具有正确类型的数组。例如:

public class Foo<T extends Comparable> {
    private Class<T> type;

    public Foo(Class<T> type) {
        this.type = type;
    }

    T[] createArray() {
        return (T[])Array.newInstance(type, 1);
    }

    public static void main(String... args) {
        Foo<String> foo = new Foo<>(String.class);
        String[] ss = foo.createArray();
    }
}

(你可能仍会收到编译器的警告,因为newInstance的返回类型是Object。你可以忽略它,因为它返回的对象是一个正确类型的数组。)< / p>