0

I have this generic class:

public class MyClass<T> {

    public void myMethod(T arg) {
        // ...
    }
}

How can I get an instance of this class which uses the class of an object as generic type T?

That is if I have:

SomeClass o = new SomeClass()

How can I get an instance of MyClass<SomeClass> by getting the runtime class of o?

Basically what I need is something like this (I know this doesn't make sense... it's just to give an idea):

MyClass<o.getClass()> m = new MyClass<o.getClass()>()

Is it possible? If not, can I achieve my goal of having an instance of MyClass which has a method that takes an argument of the same type of the runtime type of o? (yes, it has to be that exact type, cannot be a superclass...)

Reflection is an option here!

Thanks!

jamp
  • 2,159
  • 1
  • 17
  • 28
  • Generics don't exist at all at runtime. – SLaks Jun 12 '14 at 15:49
  • @Adam Arold how are they the same question? – jamp Jun 12 '14 at 15:55
  • They're not. You don't want to determine the generic type of a given generic object, you want to create one using a given runtime-determined type. Interesting question. – Ray Jun 12 '14 at 15:56
  • This question has been answered like 313432 times. I have answered it at least 2-3 times. Do some research before you ask something here. – Adam Arold Jun 12 '14 at 15:57
  • @Adam Arold I did, and didn't find it... I don't see the connection with the question u linked... – jamp Jun 12 '14 at 15:59
  • Looks like he had a point [here](http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java). – Misha Jun 12 '14 at 16:06
  • @Misha I still don't see a connection to my question, if you do, could you please give an answer to my specific case? – jamp Jun 12 '14 at 16:12
  • I think part of the issue is that you're posing an impossible question: "How can I get an instance of MyClass by getting the runtime class of o?" Due to type erasure, generics don't exist at runtime (for the most part), so you can't create an instance of `MyClass` at runtime; you can only create `MyClass` instances. An alternative could be to pass a `Class` instance for a type token, but whether that would work for you, I'm not sure. It's worth a try. – awksp Jun 12 '14 at 16:36
  • 1
    Can you show an example of where you would use this? – Sotirios Delimanolis Jun 12 '14 at 18:01
  • @Sotirios Delimanolis I need to use this in combination with Guava's EventBus... I need to dynamically create listeners for specific events classes – jamp Jun 13 '14 at 11:07

1 Answers1

2

Because of runtime type erasure, the runtime object created by MyClass<X> and MyClass<Y> will be identical. The fact that new MyClass<X>().myMethod() can be called on an X but not on a Y is a compile-time fact, not a run-time one. The compile-time question is "can it be called on this variable", not "can it be called on objects with the same result of getClass()".

You can create factory methods to create generic instances of your class based on the compile-time types of Class objects, or of the actual objects you wish to use it with:

public class MyClass<T> {
    // ...

    public static <T> MyClass<T> forClass(Class<T> c) {
        return new MyClass<T>();
    }

    public static <T> MyClass<T> forObject(T object) {
        return new MyClass<T>();
    }
}

If you want your generic class's method to actually have runtime type checking, that's possible, too. Just store a Class object for the type in your MyClass instance, and use its isInstance() or cast() method to check the type of the argument to your method. You have to do this manually, because this is not what is usually done for ordinary generic classes, which is because it is usually unnecessary.

Dan Getz
  • 8,774
  • 6
  • 30
  • 64