1

I have a class

public abstract class FakeClass<T extends MyClass> {
    protected HashMap<Character, T> myMap;

    private void myMethod(){
        myMap.put('c', /*???? I need to instatiate something of type T here.*/)
    }
}

As you can see, I can't figure out how to instantiate something of type T. Is this possible? If so can someone point me in the right direction to do it?

Thanks!

djs22
  • 1,068
  • 3
  • 13
  • 28
  • Please paste the code for "MyClass" so we can help you. – MacGyver Jul 25 '11 at 00:22
  • @Mr. MacGyver That probably isn't going to help because `MyClass` isn't always going to match `T extends MyClass`. What would be helpful is some context as to what that map is going to be used for. – trutheality Jul 25 '11 at 00:26

2 Answers2

7

This can only be done by passing some information about T to myMethod(). One approach, described in this thread, is to pass a factory object for T. A special case of this, described in this thread, is to pass a Class<T> type argument to myMethod(), which can then use type.newInstance() to create a new T object using the default constructor. (This will fail if T does not have a default constructor.) The Class object serves as the factory object for T.

The reason we need all this is due to type erasure in Java.

Ted Hopp
  • 222,293
  • 47
  • 371
  • 489
  • It is so unfortunate that Java generics were designed/implemented like this. – luiscubal Jul 25 '11 at 00:30
  • How does type erasure play into this? I'd say the reason we need all this is that constructors don't get inherited in the same way that other methods are. – trutheality Jul 25 '11 at 00:32
  • @trutheality If there was no type erasure, the JVM(rather than just the Java compiler) would know what T really is, so "new T()" would be meaningful. – luiscubal Jul 25 '11 at 00:34
  • @luiscubal: Generics have very little to do with this. You'd have the same problem without generics (and the same solution) if you wanted to create an "instance" of an interface. – trutheality Jul 25 '11 at 00:34
  • @luiscubal: Calling `new T()` is a compiler error if `T` is a class with a private default constructor. So `new T()` should be illegal no matter how you twist it. Unless you resolve all the types at compile-time a-la C++ templates. – trutheality Jul 25 '11 at 00:36
  • @trutheality - In C#, there is no type erasure, so (with some extra tricks such as explicitly indicating that T must have a public default constructor) "new T()" is valid. So, if it wasn't for type erasure, it would be trivial to add support for this in Java. – luiscubal Jul 25 '11 at 00:38
  • @luiscubal The problem is the "explicitly indicating that T must have a public default constructor" part. Not type erasure. – trutheality Jul 25 '11 at 00:43
  • 1
    @trutheality - I agree that no type erasure is a necessary but not sufficient condition for "new T()" to be valid, if that's what you meant. It is "necessary" because even if T had a default constructor, it's meaningless if the JVM doesn't know what T is to begin with. – luiscubal Jul 25 '11 at 00:44
  • @luiscubal let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1788/discussion-between-trutheality-and-luiscubal) – trutheality Jul 25 '11 at 00:50
0

Usually, the point of generics is to be able to accept an unknown-at-compile-time type as input.

You can't instantiate an unknown class (because it might not have a visible constructor). If you just need a placeholder to put into the map, you can put a null value.

Without knowing more context, there isn't much more that anyone can do.

trutheality
  • 21,548
  • 6
  • 47
  • 65