4

When I compile this code:

public class OuterClass<T>
{
    class InnerClass
    {
       T temp;
    }
    
    private InnerClass[] theArray;
    
    public OuterClass(int size){
       this.theArray = new InnerClass[size];
  }
}

I get this error:

OuterClass.java:10: error: generic array creation
      this.theArray = new InnerClass[size];

So my question #1 is: why is creating an array of InnerClass a problem? After all, it's an array of objects, not of a generic type.

My question #2 is: why does modifying the code (see below) resolve the problem?

public class OuterClass<T>
{
    class InnerClass<U>  //changed this line
    {
       T temp;
    }
    
    private InnerClass<T>[] theArray;  //changed this line
    
    public OuterClass(int size){
       this.theArray = new InnerClass[size];
  }
}

2 Answers2

4

Think about what type of array you are instantiating here. In the first case, it is a

OuterClass<T>.InnerClass[]

Note that this type is a parameterised type (<T>), and you are not allowed to create arrays of parameterised types.

In the second case, since the declaration of InnerClass is parameterised, the name "InnerClass" actually refers to a raw type (because you are not specifying the type arguments), and because it is a raw type, the type of array that you are creating becomes:

OuterClass.InnerClass[]

Note that OuterClass loses its type parameter too, because you are using a raw type. This is now not a parameterised type, so you are allowed to create such an array.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • OK thanks, so the line `private InnerClass[] theArray;` makes `theArray` have a type of `OuterClass.InnerClass[]`, but then when I do `this.theArray = new InnerClass[size];`, I'm instantiating the array with a raw type? – HangingParens Feb 19 '21 at 03:07
  • 1
    @HangingParens Yes, and it is possible to assign a value of type `OuterClass.InnerClass[]` to a variable of type `OuterClass.InnerClass[]`, which is why there is no error about the assignment statement. – Sweeper Feb 19 '21 at 03:09
  • OK good, so if I change `private InnerClass[] theArray` to `private InnerClass[] theArray`, that would also work, because now I am assigning a raw type to a variable of a raw type? – HangingParens Feb 19 '21 at 03:11
  • 1
    @HangingParens Yes, but you should avoid using raw types, as said in [this post](https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it). – Sweeper Feb 19 '21 at 03:13
  • In [that post](https://stackoverflow.com/questions/2770321/) it says `MyType.Inner inn` is raw. From what we've said above, `MyType.Inner` would be parameterized, but if we change `class Inner { }` to `class Inner { }`, then `MyType.Inner` would be raw? – HangingParens Feb 19 '21 at 03:26
  • @HangingParens I don't think `MyType.Inner` is a valid type at all... – Sweeper Feb 19 '21 at 03:31
0

The following code would work as well:

public class OuterClass<T>
{
    class InnerClass<U>  //changed from T to U
    {
       U temp;
    }

    private InnerClass<T>[] theArray;

    public OuterClass(int size){
       this.theArray = new InnerClass[size];
  }
}

In the first case, T is not recognized as a type parameter in the inner class. In case 2, you have provided a type parameter that you have selected to also be T for the inner class, but in fact has nothing to do with the type parameter of the outer class.

Tarik
  • 10,810
  • 2
  • 26
  • 40