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"?

+2


source to share


7 replies


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.

+9


source


Casting from the superclass can work, so it is allowed (at compile time). Casting from a completely different class is not allowed, for example:



Integer a = 1;
String b = (String)a; // compile error
String b = (String)(Object)a; // runtime error

      

+4


source


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.
+3


source


The fill type of an object happens at runtime, so the compiler doesn't recognize it

+1


source


Not. v

is Vehicle

, and it could be attributed to Bike

. It is not up to the compiler to determine the actual run-time types of each object (especially because sometimes this is not possible).

0


source


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.

0


source


This is a runtime error because you have already defined the variable v

as Car

. You cannot convert Car

to Bike

.

The compiler does not check for such value assignments because compilers do not check semantics at all.

0


source







All Articles