I implemented this code:
class A {
//some code
}
class B extends A {
// some code
}
class C {
public static void main(String []args)
{
B b1 = (B) new A();
A a1 = (B) new A();
}
}
Both of these lines, when compiled separately, compile fine,but give runtime error
with java.lang.ClassException: A cannot be cast into B
.
Why they compile well, but give a runtime error?
How to handle ClassCastException. To prevent the ClassCastException exception, one should be careful when casting objects to a specific class or interface and ensure that the target type is a child of the source type, and that the actual object is an instance of that type.
Introduction. ClassCastException is a runtime exception raised in Java when we try to improperly cast a class from one type to another. It's thrown to indicate that the code has attempted to cast an object to a related class, but of which it is not an instance.
Straight from the API Specifications for the ClassCastException : Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. So, for example, when one tries to cast an Integer to a String , String is not an subclass of Integer , so a ClassCastException will be thrown.
Variables of type A
can store references to objects of type A
or its subtypes like in your case class B
.
So it is possible to have code like:
A a = new B();
Variable a
is of type A
so it have only access to API of that class, it can't access methods added in class B which object it refers to. But sometimes we want to be able to access those methods so it should be possible to somehow store reference from a
in some variable of more accurate type (here B
) via which we would be able to access those additional methods from class B.
BUT HOW CAN WE DO THAT?
Lets try to achieve it this way:
B b = a;//WRONG!!! "Type mismatch" error
Such code gives compile time Type mismatch
error. It happens to save us from situation like this:
class B1 extends A
class B2 extends A
and we have A a = new B1();
.
Now lets try to assign B1 b = a;
. Remember that compiler doesn't know what actually is held under variable a
so it needs to generate code which will be safe for all possible values. If compiler wouldn't complain about B1 b = a;
it should also allow to compile B2 b = a;
. So just to be safe it doesn't let us do it.
So what should we do to assign reference from a
to B1
? We need to explicitly tell compiler that we are aware of potential type mismatch issue here, but we are sure that reference held in a
can be safely assigned in variable of type B
. We do so by casting value from a
to type B
via (B)a
.
B b = (B)a;
But lets go back to example from your question
B b1 = (B) new A();
A a1 = (B) new A();
new
operator returns reference of the same type as created object, so new A()
returns reference of the type A
so
B b1 = (B) new A();
can be seen as
A tmp = new A();
B b1 = (B) tmp;
Problem here is that you can't store reference to object of superclass in variable of its derived type.
Why such limitation exist? Lets say that derived class adds some new methods that supertype doesn't have like
class A {
// some code
}
class B extends A {
private int i;
public void setI(int i){
this.i=i;
}
}
If this would be allowed
B b = (B)new A();
you could later end up with invoking b.setI(42);
. But will it be correct? No because instance of class A doesn't have method setI
nor field i
which that method uses.
So to prevent such situation (B)new A();
at runtime throws java.lang.ClassCastException
.
The reason it fails at runtime is that the object isn't a B. It's an A. So while some As can be casts as Bs, yours cannot.
The compilier just can't analyze everything that happened to your A object. For example.
A a1 = new B();
A a2 = new A();
B b1 = (B) a1; // Ok
B b2 = (B) a2; // Fails
So the compilier isn't sure whether your A object is actually castable to a B. So in the above, it would think that the last 2 lines were ok. But when you actually run the program, it realizes that a2
is not a B, it's only an A.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With