Consider this simple code:
class A {}
class B extends A {}
public class TestClass {
public static void main(String args[]) {
A[] a, a1;
B[] b;
a = new A[10];
a1 = a;
b = new B[20];
a = b; // 1
b = (B[]) a; // 2
b = (B[]) a1; // 3
}
}
Look closely at lines which I commented 1,2 and 3. The line 1 will be allowed during compilation, since assignment is done from a subclass reference to a superclass reference.
The cast in line 2 is needed because a superclass reference is assigned to a subclass reference variable. And this works at runtime because the object referenced to by a is actually of an array of B (line 1).
Now, here's where lies my confusion: line 3 will throw a java.lang.ClassCastException. Now, this means that during runtime, the program realizes that the actual object is not an array of B but is an array of A.
This is exactly what I don't understand. Doesn't B extends A? So it satisfies the condition B IS-A A, correct? And therefore, shouldn't line 3 not throw any exception during run time?
a1
is an array of A
elements. Since B
extends A
, all instances of B
are also instances of A
, but not all instances of A
are instances of B
. You could define a class C
that also extends A
and assign instances of that class to the a1
array. Such instances are not instances of B
.
Therefore you can't cast an array of A
elements to an array of B
elements.
You forgot, that arrays are classes by themselves, and they have their own cast and assignment rules.
Consider this:
A[] aa = new A[0];
B[] bb = new B[0];
System.out.println(aa.getClass());
System.out.println(bb.getClass());
System.out.println(aa.getClass().isAssignableFrom(bb.getClass()));
System.out.println(bb.getClass().isAssignableFrom(aa.getClass()));
Output:
class [Lstuff.small.Try47$A;
class [Lstuff.small.Try47$B;
true
false
Thus, an A[] variable can indeed be assigned a B[], but not the other way around.
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