Reputation: 10574
Attempting the following:
class Base {
public Base(){
}
}
class Derived extends Base {
}
public class Main
{
public static void main (String[] args)
{
Derived derived = (Derived) new Base();
}
}
Causes a CastClassException
, but compiles successfully. The comments on this question suggest that it's impossible for the compiler to figure out what type new Base()
has until runtime -- but why should that be the case? I know that in other type systems the compiler can always infer the type of any expression, and the Java compiler certainly does some type inference with e.g. lambda expressions. And it must, at some point, know what type new Base()
has if it's going to emit the correct bytecode.
Is there a theoretical limitation that prevents the Java compiler from catching this before the program runs, or is it an implementation choice?
Upvotes: 2
Views: 743
Reputation: 47729
Any rational implementation of a language that permits subclassing will have the possibility of a cast exception (or its equivalent).
The power of a subclassing scheme is that you can have methods that operate on a generic superclass without having to know the specific subclass. But sooner or later one will need to do operations specific to the subclass, and for that one must cast the reference to the subclass. If that cast is erroneous, because you mistook the actual class of the object, then a cast exception should logically occur.
You can probably hide the cast exception behind some mechanism which, say, returns a NULL if the object was not the right type, but that's simply replacing one exception with another.
Upvotes: 3
Reputation: 310883
The result of new Base()
is a Base
, which in any other context could be a Derived.
The compiler doesn't propagate the special knowledge that in this case it really is a Base.
Is there a theoretical limitation that prevents the Java compiler from catching this before the program runs, or is it an implementation choice?
It's an implementation choice not to make a special case of it.
Upvotes: 1
Reputation: 279940
public static void main(String[] args) throws Exception {
Derived derived = (Derived) getObject();
}
public static Base getObject() {
if (Math.random() > 0.5) {
return new Base();
} else {
return new Derived();
}
}
What now? How will the compiler know? The compiler is (mostly) limited to static information. The type of an object is dynamic information.
Upvotes: 6