0

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

3
Contributors
4
Replies
5
Views
6 Years
Discussion Span
Last Post by JamesCherrill
0

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

0

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!

0

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?

0

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

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.