问题
Imagine a class Cottage extending Building and the code
Building building = new Building();
Cottage cottage = (Cottage)building;
Now, it totally makes sense that Building cannot be casted to Cottage considering the nature of java's inheritance, but what doesn't make sense (to me) is that this compiles. Why does it compile and then throw a runtime ClassCastException?
Isn't it obvious that building is a reference to a Building object before actually running the program?
Being such a general question, I know I am getting a possible duplicate for this one :) but I couldn't find an answer to WHY DOES IT COMPILE question :)
EDIT2 I accepted a great answer here (let alone the discussion below it :) ), but I still find the accepted answer in Java casting resulting in run-time error instead of compilation error the most interesting...
EDIT I edited IllegalCastException and put the correct ClassCastException
回答1:
That's because, compiler does not know what object does your reference Building
is referring to.
So, in the below case, where you have a base class reference, pointing to sub class object: -
Building building = new Cottage();
Cottage cottage = (Cottage)building;
It would work perfectly fine. So, it's completely a runtime decision, as to whether it is a valid cast or not. Hence, compiler won't throw error for that.
Isn't it obvious that building is a reference to a Building object before actually running the program?
No. Absolutely not. The type of object being referenced, is not known till runtime. Always remember that, Compiler always checks the reference type. Actual object type is checked at runtime.
This concept is known as Polymorphism, where you can have the same reference type to point to objects of various subtypes. You can google it, and would get lots of resources to read.
回答2:
Part of the function of casting is it makes the compiler shut up, you are saying that you know better than the compiler what the object you're casting is. If the cast is not accurate you get an exception.
Maybe you expect the compiler is tracking what object things are pointing to and working out if the reference is plausible. The compiler is not that smart and is easily fooled, see this snippet:
int i = 1;
System.out.println((Number)i);
Object o = i;
System.out.println((String)i); // won't compile (primitive-to-ref-type cast)
System.out.println((String)o); // compiles (thanks to autoboxing)
The compiler cares only about preventing conversions between primitives and reference types.
回答3:
Consider creating an Cottage(Subclass) object with Building(super class) reference
Building b= new Cottage();
Cottage c = (Cottage) b;
The above code is legal, thus the compiler wouldn't know what object does the reference variable c
refer to at run time, thus compiler wouldn't throw an error.
Why does it compile and then throw a runtime IllegalCastException?
BTW, it throws ClassCastException when you try to cast an superclass object into subclass, not IllegalCastException.
来源:https://stackoverflow.com/questions/14467999/cast-a-superclass-to-a-subclass