public class InterfaceCasting {
private static class A{}
public static void main(String[] args) {
A a = new A();
Serializable serializable = new Serializable(){};
a = (A)serializable;
}
}
Compilation succeed but Runtime exception
Exception in thread "main" java.lang.ClassCastException: InterfaceCasting$1 cannot be cast to InterfaceCasting$A
WHY COMPILATION SUCCEED? Compiler must known that serialiazable is not A?
As you point out, this will compile:
interface MyInterface {}
class A {}
public class InterfaceCasting {
public static void main(String[] args) {
MyInterface myObject = new MyInterface() {};
A a = (A) myObject;
}
}
This however, will not compile:
interface MyInterface {}
class A {}
public class InterfaceCasting {
public static void main(String[] args) {
A a = (A) new MyInterface() {}; // javac says: "inconvertible types!"
}
}
So, what's going on here? What's the difference?
Well, since MyInterface
is simply an interface, it could very well be implemented by a class that extends A, in which case the cast from MyInterface
to A
would be legal.
This code for instance, will succeed in 50% of all executions, and illustrates that the compiler would need to solve possibly undecidable problems in order to always "detect" illegal casts at compile time.
interface MyInterface {}
class A {}
class B extends A implements MyInterface {}
public class InterfaceCasting {
public static void main(String[] args) {
MyInterface myObject = new MyInterface() {};
if (java.lang.Math.random() > 0.5)
myObject = new B();
A a = (A) myObject;
}
}
Java language specification states, that:
Some casts can be proven incorrect at compile time; such casts result in a compile-time error.
And later on the show The detailed rules for compile-time legality of a casting conversion of a value of compile-time reference type S to a compile-time reference type T - beware, they are very complex and hard to understand.
The interesting rule is:
In your example, it's perfectly clear, that the cast is illegal. But consider this slight change:
public class InterfaceCasting {
private static class A{}
private static class B extends A implements Serializable{}
public static void main(String[] args) {
A a = new A();
Serializable serializable = new B(){};
a = (A)serializable;
}
}
Now a cast from a Serializable
to A
is possible at runtime and this shows, that in those cases, it's better left to the runtime to decide if we can cast or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With