Why does it compile when casting to an unrelated interface?
The compiler does not know that this won't work: You could have a subclass of BlackInk that implements Printable. Then the cast would be fine.
In situations where the compiler knows it won't work, you will get an error.
For example, if you make BlackInk final
(so that there can be no subclasses) you get an error.
Why casting to unrelated interface produce ClassCastException instead of compile time exception?
Mark Bug
as final
and you will get your compiler error as expected.
This is because Bug
could have a subclass that does implement Tree
. If bug
actually stores a reference to an instance of that subclass, then the cast will succeed. Since there is a chance that the cast can succeed, the compiler doesn't stop you from casting.
In most cases, you can cast from any non-final class to any interface. According to the JLS §5.5.1, when you try to cast a variable of reference type S
to interface T
:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
Casting a class to an unrelated interface
The reason this compiles
interface Furniture {}
class Test {
public static void main(String[] args) {
Furniture f;
Cat cat = new Cat();
f = (Furniture)cat; //runtime error
}
}
is that you may very well have
public class CatFurniture extends Cat implements Furniture {}
If you create a CatFurniture
instance, you can assign it to Cat cat
and that instance can be casted to Furniture
. In other words, it's possible that some Cat
subtype does implement the Furniture
interface.
In your first example
class Test {
public static void main(String[] args) {
Chair chair = new Chair();
Cat cat = new Cat();
chair = (Chair)cat; //compile error
}
}
it's impossible that some Cat
subtype extends Chair
unless Cat
itself extends from Chair
.
Cast to unimplemented interface compiles
Actually, in Java it is perfectly valid to cast one related type to another (even if the casting makes little sense). You will get an error during runtime if the types are not compatible.
For example :
public static void main(String[] args) {
String s = (String) new Object();
System.out.println(s.intern());
}
Compiles fine but gives Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
during runtime
at Sample.main(Sample.java:5)
Related Topics
Java 8: Where Is Trifunction (And Kin) in Java.Util.Function? or What Is the Alternative
How to Get Current Working Directory in Java
No Exception While Type Casting with a Null in Java
Differences Between Java 8 Date Time API (Java.Time) and Joda-Time
Limiting Java Ssl Debug Logging
Passing Pointers Between C and Java Through Jni
Difference Between One-To-Many, Many-To-One and Many-To-Many
How to Convert/Parse from String to Char in Java
Implementation Difference Between Aggregation and Composition in Java
Create MySQL Database from Java
Random "Element Is No Longer Attached to the Dom" Staleelementreferenceexception
Correct Way of Throwing Exceptions with Reactor
Integer Arithmetic in Java with Char and Integer Literal
How to Enable Commit on Focuslost for Tableview/Treetableview