I was trying to find the algorithmic definition of convertible (and thus inconvertible) types in Java.
In my opinion a CORRECT compiler should block at compile-time explicit and implicit castings between expressions having inconvertible static types, whatever the definition of inconvertible would be.
On the other hand, since it would be nice if each reference had a dynamic type which is a subtype of its static type, in order to prevent ClassCastExceptions at run-time, the compiler should always block castings between types that have no common subtypes.
A candidate definition that makes sense to me is be the following:
- Two classes A and B are convertible iff either A is a subtype of B or B is a subtype of A
- An interface I and a class C are convertible iff either C implements I or I and C have a common subtype (a class that implements I and extends C, possibly in an indirect way)
- Two interfaces I1 and I2 are convertible iff they have a common subtype (a class or another interface)
However the following snippets do NOT give compilation errors (only warnings for example in IntelliJIDEA):
interface A {}
class B {}
class Test {
public static void main(String[] args) {
B b = new B();
A a = (A)b; // this casting will produce a run-time error
}
}
interface M {}
interface N {}
class A implements M {}
class B extends A {}
class C extends A implements N {}
class Test {
public static void main(String[] args) {
N x = new C();
M y = (B)x; // this casting will produce a run-time error
}
}
interface M {}
class A implements N{}
interface N {}
class Test {
public static void main(String[] args) {
N x = new A();
M y = (M)x; // this casting will produce a run-time error
}
}
In conclusion I want to understand if there is an official definition of (in)convertible types in the Java specs, and whether it has been correctly implemented in the existing compilers.