I am trying to understand why the compiler doesn't print a compile-time error in this code below. It compile, but obviously won't work.
Someone know why the compiler allow it?
public class Tests {
public static void main(String... args){
// Lines below are acceptable for the compiler and work well in runtime.
GenericClass<FooClassWithFooInterface> genericClass1 = new GenericClass();
genericClass1.print(new FooClassWithFooInterface());
// Lines below are oddly acceptable for the compiler and, obviously, won't work in runtime.
GenericClass genericClass2 = new GenericClass();
genericClass2.print(new FooClassWithFooInterface());
genericClass2.print(new FooClass()); // why the compiler not throw a compile-time error?
}
}
class GenericClass<T extends FooClass & FooInterface>{
public void print(T t){
t.fooMethod();
}
}
class FooClass{
}
interface FooInterface{
public void fooMethod();
}
class FooClassWithFooInterface extends FooClass implements FooInterface{
@Override
public void fooMethod() {
System.out.println("foo");
}
}
Console output:
foo
foo
Exception in thread "main" java.lang.ClassCastException: FooClass cannot be cast to FooInterface
at GenericClass.print(Tests.java:18)
at Tests.main(Tests.java:11)
I have created fooMethod() just to force this runtime error.
I think that the compiler can check that new FooClass()
doesn't match with <? extends FooClass & FooInterface>
and force a compile-time error.
if we change the GenericClass to T extends FooClassWithFooInterface
, instead of T extends FooClass & FooInterface
, the compiler show finally the compile-time error :
class GenericClass<T extends FooClassWithFooInterface>{
public void print(T t){
t.fooMethod();
}
}
Also, I did not find any restriction related to this issue in Restrictions on Generics(The Java Tutorial)