简体   繁体   中英

Down casting Object array to array of type parameter

How is the statement in the GenericArrayCreationIsDisallowedInJava constructor working? Could some1 please explain ?

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? 

    }

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

It is not entirely clear what you think the above does, but one thing it most definitely doesn't do is create an array of I . The only part responsible for choosing the type of the array comes after the new keyword: It's an array of Object s, unsafely cast to I[] .

The compiler must allow the line to compile because it doesn't know anything about the type I : it could as well be Object , so the line is legal.

Also note that the erased type of I[] is Object[] : the actual type (in the bytecode) of the i variable is Object[] . Therefore the assignment succeeds at runtime no matter what type the instance is parameterized with.

A ClassCastException will only be thrown if the array is assigned back to a reifiable type. For example:

GenericArrayCreationIsDisallowedInJava o =
        new GenericArrayCreationIsDisallowedInJava<String>(2);

String[] strs = o.i; // ClassCastException thrown here

During the type erasure process, the compiler inserts the cast to String[] in the line assigning strs . This demonstrates the need to keep i from "leaking" outside the class that is using it.

To understand what is going on, simply consider the same code after type erasure (just remove type parameters and insert casts if necessary):

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? 

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM