Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Array Creation Compilation Error From Inner Class

I'm trying to implement a linked collection using generics, something like the following.

public class A<E> {

  private class B {

    private B[] b;
    private E item;

    private B() {
      this.b = new B[2];
    }

  } // end inner class B

} // end class A

A is the collection and B an element or node in the collection with an array referencing successors/predecessors and an item.

The array creation is not allowed. The error I get is generic array creation. Am I right to think that what it's actually creating is an array of A<E>.B?

If not, what's causing the error?

If so, how can I get around this?

I have obviously omitted a substantial amount of code, if what I've provided is not enough please let me know. Any advice would be appreciated. Thank you.

EDIT 1: I should have mentioned that the parameterized type must be the same in A as in B. So passing <E> to the inner class is not possible, as it creates E#2 and leaves A with E#1.

like image 773
comfortablejohn Avatar asked Oct 07 '22 19:10

comfortablejohn


2 Answers

You call B inherits the generic from the outer class, as it is not static. And you can't just make it static, because it will then need E also.

So your B.b array will indeed need a type that is generic, i.e. A<E>.B or if you'd change your code to a static inner class, A.B<E> (if you would use private static class B<E>).

In Java, due to the way generics are implemented (by erasure), the type of the array is not well-defined. On one hand, it should be an array of B, on the other hand, it should be an array of Object.

The most workable solution seems to be to use Object[] and cast explicitly. If you want increased type safety, you can of course use an ArrayList<B>, which internally uses Object[], too!

In you particular code, B b1, b2; might also be an option which is actually faster (no bounds checking) and needs less memory (no array object; no size information).

like image 102
Has QUIT--Anony-Mousse Avatar answered Oct 10 '22 07:10

Has QUIT--Anony-Mousse


B is a non-static inner class. That means it has a reference to an instance of the enclosing class. So it is implicitly parameterized by the type parameter of outer class. So when you write B, it means A<E>.B. To create an array, you should use the raw class. However, B is not the raw class; to refer to the raw class you need to explicitly qualify it: A.B

So this is that you want:

this.b = new A.B[2];
like image 43
newacct Avatar answered Oct 10 '22 08:10

newacct