Why Does It Compile When Casting to an Unrelated Interface

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
at Sample.main(Sample.java:5)
during runtime



Related Topics



Leave a reply



Submit