I have a problem involving Generics. Here's a simplified version:
Suppose I have a generic method to add a new element to a (possibly empty) ArrayList, like this:

<T> void addNewTo(ArrayList<T> list)

What I need to do is to determine the correct class for the ArrayList elements so as to create the right kind of new element. Ie, I really want to say

<T> void addNewTo(ArrayList<T> list) {
   list.add(new T());
}

However, because of the way Java implements generics via type erasure, you can't do that. There are some really ugly work-arounds for the general case of implementing "new T()", but maybe there's a better way in this particular case?
I'd be very grateful for any ideas or suggestions.
Thanks,
J

Haven't used generics in a while, but is something like this what your looking for:

import java.util.ArrayList;

public class GenericTest<T> {
  private Class<? extends T> instance;
  
  public GenericTest( Class<? extends T> instance ) {
    this.instance = instance;    
  }  
 
  public <T> void addNewTo(ArrayList<T> list) 
                  throws InstantiationException, IllegalAccessException {       
    list.add( (T) instance.newInstance() );    
  }   
}

It'll cause an unchecked cast warning, but its a suggestion!

Then in the main you can pass a Class object corresponding to <T> into the constructor.
Something like:

String string = "";
Class<? extends String> tClass =  string.getClass();
GenericTest<String> str = new GenericTest<String>( tClass );

Of course I could be totally off the plot! Its been a while since I used generics.. :)

Hi chaospie, thanks for the reply.
Yes, that's an approach I found (thanks Google) - you may need to make some of those things final, for reasons I coudn't be bothered to read up. It will work, but its the kind of mess I was hoping to avoid. And if I'm going to have to pass a new parameter to the constructors, in this particular app, I may as well just pass a Class that I can run newInstance on direcly (or an instance that I can use as a template).
I had some fun with the idea of populating the ArrayList at the beginning with one dummy entry, using that as a template,then deleting it after I've done all the adding. The template bit is dead easy:

list.add((T) (list.get(0).getClass().newInstance()));

(with Exceptions as in your code), but that really is a kludge.
It's maddening that I can't find a way of determining what the class of the instances of an ArrayList need to be!

As already noted, you can't use the 'new' expression to create a new object at runtime given the way generics are implemented in Java. IMO, the cleanest (type-safe without any warning) approach you can come across can be achieved by passing in the class of the object you have to create. E.g.

private static <T> T addToList(List<T> list, Class<T> klass) {
    T t = null;
    try {
        t = klass.newInstance();
        list.add(t);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return t;
}

But then again, I personally think that having a method given the arbitrary responsibility of creating objects and inserting into Lists is a bit off. Any "practical" scenario you have in mind which requires you to have true generics?

Any "practical" scenario you have in mind which requires you to have true generics?

Yeah, this came up as part of a fairly complex app, the details of which are not relevant here. I tried to reduce the problem to the simplest form that would have a solution directly applicable to the full problem. The real situation involves processing input to create the objects, which are then inserted into a Collection - they're not just virgin objects.

I've spent a few more hours on the web, and I'm now pretty certain that the the kind of solution I'm looking for doesn't exist. I'm going to go with a factory method appraoch. I'll mark this "solved", since there is no "now known to be unsolvable" option!
J

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.