tags:

views:

62

answers:

1

I am trying to do one of the following:

Dummy d = (Class<Dummy>)super.getEntity();  // incompatible Types - cannot cast
Dummy d = (Dummy)super.getEntity();  // incompatible Types - cannot cast
d.foo();

or

Class<Dummy> d = (Class<Dummy>)super.getEntity(); // works
d.foo(); // method cannot be found

Dummy d is defined in an abstract superclass as follows:

Class<T> dummy;
public Class<T> getEntity() { return dummy; }

Is there any way to call a method (foo) in an object of Generic class type? The point is that the superclass should NOT care about the type of the object, so that functionality can vary by the extending classes.

+2  A: 

Your getEntity() method returns a class token, not an instance of that class, so you can't call foo() on it, only the methods defined in the interface of java.lang.Class. You need to instantiate that class first (by calling newInstance() - it requires that the class has a public default constructor), then you have a class object, upon which you may call foo():

Class<Dummy> clazz = super.getEntity();
try {
  Dummy d = clazz.newInstance();
  d.foo();
} catch (...) {
}

Notes:

  • since getEntity() is generic, it will return the proper class type, thus the cast to Class<Dummy> is not needed,
  • Class.newInstance() may throw various exceptions, which you must handle, hence the try-catch block. This is one of the reasons reflection is not a preferred way of solving such issues,
  • since in the derived class you know the exact type parameter used in the base class, this code is unnecessarily verbose and rather contrived.

Alternatively, you may prefer returning T from getEntity() instead of Class<T> - this way you can call foo() directly on the object returned. Note that since you can't instantiate generic types directly, you need to either pass an instance of the class to the superclass (e.g. as a constructor parameter, or through an overridden virtual method), or create it using reflection as described above.

Here is how to do it using a constructor parameter:

public abstract class ABC<T> {
  private T dummy;
  public ABC(T dummy) { this.dummy = dummy; }
  ...
  public T getEntity() { return dummy; }

}

public class DEF extends ABC<Dummy> {
  public DEF() {
    super(new Dummy(); }
  }
  public void doSomething() {
    Dummy dummy = getEntity();
    dummy.foo();
  }
}
Péter Török
dummy is instantiated in the constructor, public abstract ABC<T> {
dummy is instantiated in the constructor, public abstract ABC<T> { public ABC(Class<T> dummy) { this.dummy = dummy; } ... } If dummy is not an instance, how can I get a reference to its instance?
@staley, see my code example.
Péter Török