Java casting leading to runtime error instead of compile error
The following piece of code will lead to runtime:
class Vehicle {
public void printSound() {
System.out.print("vehicle");
}
}
class Car extends Vehicle {
public void printSound() {
System.out.print("car");
}
}
class Bike extends Vehicle {
public void printSound() {
System.out.print("bike");
}
}
public class Test {
public static void main(String[] args) {
Vehicle v = new Car();
Bike b = (Bike) v;
v.printSound();
b.printSound();
}
}
My question is, why does this result in a runtime error but not a compilation error? Doesn't the compiler know that "v" is already a "car" and cannot be thrown into a "bike"?
source to share
In theory, the compiler could say to itself: " v
is a local variable that is assigned as Car
. In no case before attempting to cast to Bike
it does change its value, and there is no way for it Car
to Car
be successfully clicked on Bike
. So this is an error."
However, I don't know of a Java compiler that will do this analysis for you. This is really only worth it in the simplest cases. Instead, the behavior is that the compiler sees the cast and explains what can be distinguished Vehicle
before Bike
, and therefore allows it.
In general, this is what the cast means: it tells the compiler that even if this assignment might fail, you are pretty sure it won't. In exchange for being able to compile your code, you assume the risk of a runtime exception.
source to share
For
R r = /* some code to initialize "r" */
T t = (T) r;
The Java Language Specification says:
If R is a regular class (not an array class):
- If T is a class type, then R must be either the same class as T, or a subclass of T, or an exception is thrown at runtime.
- If T is an interface type, then R must implement the T interface or throw an exception at runtime.
- If T is an array type, then an exception is thrown at runtime.
source to share
Java semantics says this should result in a runtime error. In this case, you can look at the code and see that it will definitely throw an error at runtime, but how does the compiler know what is ClassCastException
not what you want?
Editors like IntelliJ and Eclipse can (and do) spot these errors and warn you about them, but Java rules say this is legitimate code that should compile.
source to share