I was recently caught flat-footed by the following Java code:
interface Common {}
interface A extends Common {}
static class B implements Common {}
static class Impl {
  private A a;
  public <T extends A> T translate() {
    return (T) a;
  }
}
static class Usage {
  public void use() {
    Impl impl = new Impl();
    B b = impl.translate(); // Why does this compile?
  }
}
I would have expected that the type constraint on Impl.translate would not allow storing the result in type B to be accepted by the compiler, considering that B does not extend A.
Instead of a compiler error, the code throws an UncheckedCastException at runtime.
This only happens when the method returns the type T; if it is the method parameter instead:
  public <T extends A> void translate(T t) {}
Then instances of B are not allowed as parameters to translate, as expected.
What's going on here? Why is this allowed by Java's type system?
 
     
     
    