0

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? 

    }

}
newacct
  • 119,665
  • 29
  • 163
  • 224
rb8680
  • 279
  • 2
  • 3
  • 11

2 Answers2

4
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 Objects, 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.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
1

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? 

    }

}
newacct
  • 119,665
  • 29
  • 163
  • 224