14

I've always thought the following should work. I get an object which I know is a Class<X> where X extends some class Xyz. In order to make it type-safe I wanted to use Class.asSubclass like in the following method:

private Class<? extends Xyz> castToXyzClass(Object o) {
    final Class<?> resultClass = (Class<?>) o;
    final Class<? extends Xyz> result = Xyz.class.asSubclass(resultClass);
    return result;
}

However, in Eclipse it doesn't work, the only solution I see is an unchecked cast. I'd bet the above code must work, I've used something like this already... no idea what's wrong here.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
maaartinus
  • 44,714
  • 32
  • 161
  • 320

2 Answers2

22

asSubclass() operates on the object it's called on, not on its parameter - not what one is used to, but it reads quite well. You just have to do this:

final Class<? extends Xyz> result = resultClass.asSubclass(Xyz.class);
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
10

The asSubclass is a bit of a confusing name because you're not obtaining a Class object representing the subclass, you're obtaining the same class object that is retyped to reflect that it is a subclass of some parent class.

In fact, this method is fairly single purpose (and I think you've found it)...it's to take a raw or wildcarded class and get a better type parameter with a runtime check. It's not needed when you don't have gaps in your type information:

class Super {}
class Sub extends Super {}

//...
Class<Sub> subClass = Sub.class;

//both work, but the latter introduces a redundant runtime check
Class<? extends Super> subOfSuper1 = subClass;
Class<? extends Super> subOfSuper2 = subClass.asSubclass(Super.class);
Mark Peters
  • 80,126
  • 17
  • 159
  • 190