向下转换Object数组到类型参数的数组

时间:2013-12-29 19:09:12

标签: java arrays generics

GenericArrayCreationIsDisallowedInJava构造函数中的语句如何工作?请问有人请解释一下吗?

public class GenericArrayCreationIsDisallowedInJava<I> {


    private I[] i;


    public GenericArrayCreationIsDisallowedInJava(int n)
    {
        i = (I[]) new Object[n];//works and prints out "Created". How?
        System.out.println("Created");
    }

    public static void main(String[] args) {

        new GenericArrayCreationIsDisallowedInJava<String>(2);

        String[] strs = (String[])  new Object[2]; // throws ClassCastException. When this statement doesn't work, how is the "(I[]) new Object[n]" statement working? 

    }

}

2 个答案:

答案 0 :(得分:4)

i = (I[]) new Object[n];

上述的思考并不完全清楚,但有一点我绝对不会创建一个I的数组。唯一负责选择数组类型的部分来自new关键字:它是Object的数组,不安全地转换为I[]

编译器必须允许该行进行编译,因为它对类型I一无所知:它也可能是Object,因此该行是合法的。

另请注意,I[] Object[]类型为iObject[]变量的实际类型(字节码)为ClassCastException。因此,无论实例参数化的类型如何,赋值都会在运行时成功。

只有在将数组分配回可恢复类型时,才会抛出GenericArrayCreationIsDisallowedInJava o = new GenericArrayCreationIsDisallowedInJava<String>(2); String[] strs = o.i; // ClassCastException thrown here 。例如:

String[]

在类型擦除过程中,编译器会在指定strs的行中将强制转换插入i。这表明需要让{{1}}不要“泄漏”在正在使用它的类之外。

答案 1 :(得分:1)

要了解发生了什么,只需在类型擦除后考虑相同的代码(只需删除类型参数并在必要时插入强制转换):

public class GenericArrayCreationIsDisallowedInJava {


    private Object[] i;


    public GenericArrayCreationIsDisallowedInJava(int n)
    {
        i = (Object[]) new Object[n];//works and prints out "Created". How?
        System.out.println("Created");
    }

    public static void main(String[] args) {

        new GenericArrayCreationIsDisallowedInJava(2);

        String[] strs = (String[])  new Object[2]; // throws ClassCastException. When this statement doesn't work, how is the "(I[]) new Object[n]" statement working? 

    }

}