0

Yet another Java Generics unchecked cast question coming up:

We have something like the following:

public abstract class A<T extends A> {

    public final T doSomething() {
        return (T)this; //unchecked cast A<T> to T
    }
}

So, is this unchecked cast something we can surpress or is there really a case where this can fail?

nms
  • 183
  • 6
  • 15
  • 5
    Shouldn't the class declaration be `A>? – awksp Sep 03 '15 at 17:39
  • 1
    my view on "self type" - http://stackoverflow.com/questions/30382847 - there's also a "purist" solution for this kind of problem, `getThis` - http://stackoverflow.com/questions/31323115 – ZhongYu Sep 03 '15 at 17:42
  • 1
    You might find some more if you search for [(F-)Bounded quantification](https://en.wikipedia.org/wiki/Bounded_quantification). – Tom Sep 03 '15 at 17:49
  • @awksp yeah it probably should, but I don't think it is really needed and it would just confuse me some more. – nms Sep 03 '15 at 17:49
  • @Tom Thanks a lot! Didn't really knew how to search for this. – nms Sep 03 '15 at 17:50

2 Answers2

8

Yes, it absolutely can fail. Example:

public class B extends A<B> {
    // empty
}

public class C extends A<B> {
    // empty
}

public class AnotherClass {
    public void someMethod() {
        A<B> c = new C();
        B b = c.doSomething();  /* ClassCastException */
    }
}

Note that @awksp's suggested change to ...

abstract class A<T extends A<T>> { /* ... */ }

... does not rescue this example. With that change, the type safety diagnostic in A.doSomething() remains the only one, and of course AnotherClass.someMethod() still throws ClassCastException.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

is there really a case where this can fail?

Sure. Here's an example:

class A<T extends A<?>> {
    @SuppressWarnings("unchecked")
    T get() {
        return (T) this;
    }
}

class B<T extends A<T>> extends A<T> {

}

class C<T extends B<T>> extends A<T> {

}

Now C's method will return a C, but C isn't a legal substitution for T extends B<T>, since C doesn't extend B.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353