Hello. It's been a while since I was on here.

I'm writing a Java class with a generic type parameter. Among other things, it maintains an internal ArrayList of the same generic type as itself. In a perfect world, the code would go like this:

import java.util.ArrayList;
public class MyGenericClass<T> {
    private ArrayList<T> items;
    public MyGenericClass() {
        items = new ArrayList<T>();
    }
}

Unfortunately, we do not live in a perfect world, and this doesn't work because of type erasure.

The only solution I can think of is to instantiate a raw ArrayList. (This will never result in a ClassCastException; I can guarantee that no non-T objects will ever be stored in the ArrayList.) However, I know that this is not good practice; in fact, I've actually heard from more than one authoritative source that raw types should never be instantiated except in legacy code.

Is there a better way? Thanks for your time.

Recommended Answers

All 5 Replies

I don't have the references in front of me right now, but there is a solution that involves passing a "dummy" arg to the constructor whose type has to be <T>, then you can use the class of that param at runtime to instantiate your own vars with the same class. (I guess that's what's happening when you pass an empty array to ArrayList's toArray mathod.)

I looked at the "hideous workaround". It seems to be meant for instantiating a generic class with a wildcard as the type parameter (and I cannot imagine why anyone would want to unleash such a monstrosity). What I'm trying to do isn't as extreme as that; I just want to instantiate one generic class from inside another, and pass the type parameter from the latter to the former.

My assumption, upon seeing that this didn't work, was that it was forbidden by type erasure. However, the code from the workaround posted above (which does work; I tested it) does instantiate a generic class using a parameterized type, rather than a hard-coded one; this happens in all five Factory.make methods. How come she can do it and I can't? Is it because that code uses a method type parameter and mine uses a class type parameter? That doesn't seem right.

Presumably, this would have to be answered by someone who has a fairly deep understanding of the details of generics.

Unfortunately, we do not live in a perfect world, and this doesn't work because of type erasure.

Why doesn't it work? Instantiating a type parameter won't work, but instantiating parameterized classes which accept a type argument will. The below snippet won't work, but what you posted will.

// doesn't work
public class MyGenericClass<T> {

    private T item;

    public MyGenericClass() {
        item = new T();
    }

}

Why doesn't it work? Instantiating a type parameter won't work, but instantiating parameterized classes which accept a type argument will. The below snippet won't work, but what you posted will.

You are correct. It turned out that the class I was trying to instantiate was actually an interface. The compiler said it couldn't be instantiated, but not why, so I assumed type erasure was to blame.

Thank you for helping.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.