5

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.

4
  • Not specifically an answer to your question, but it would be better design to have two variables 'predecessor' and 'successor' of type B rather than an array of two elements. Would make your class easier to read. I guess it would also make your problem go away? Commented May 20, 2012 at 8:18
  • WRT Edit1, try a static class B<E> and you won't have the naming issue. The array will still not work, though, as it is Generic. Commented May 20, 2012 at 8:34
  • You could also get around this by using a generic collection instead of an array. Commented May 20, 2012 at 8:54
  • If b really does always have two elements, you're probably better off using two fields. Commented May 20, 2012 at 11:05

3 Answers 3

4

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).

Sign up to request clarification or add additional context in comments.

1 Comment

I had thought of using the separate b1, b2 references. It seems this is the most suitable way to go. It just makes for more complicated traversal of the collection in some methods. Thank you for your feedback, very helpful.
2

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];

Comments

-2

You need to pass E to the inner class as well

 private class B<E> {

            private B[] b;
            private E item;

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

        } // end inner class B

2 Comments

Yes. And as per my edit, I require the types to be the same in both the outer and inner class. Doing the above will mean that though they might both be turned into the same type, say A<Integer> makes them both Integers, they are not comparable or compatible when referencing between the two.
Sorry, I don't see any benefit. In your setup, it should IMHO actually be private static class B<E> to not get a name overloading, and it will still not allow the new B[2] array creation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.