4

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?

2
  • 1
    Please take the time to format the code you provide. It's really, really hard to read at the moment, with no indentation and multiple statements on one line. Please bear in mind that the purpose of Stack Overflow is to create a repository of high quality questions and answers - put the time in to make your question genuinely high quality. Commented Jan 31, 2017 at 9:33
  • 1
    "So it satisfies the condition B IS-A A, correct?" Correct. But what you would need is "A IS-A B" - but you do not have that. I guess the confusion is from here: a1 = a; a = b; // 1 - by changing the reference a you are not changing a1. It still is pointing to the same A[]. Commented Jan 31, 2017 at 9:36

3 Answers 3

7

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.

Sign up to request clarification or add additional context in comments.

4 Comments

But the code compiles fine. It throws an exception during runtime. However, let's say I made an array like this :-TestClass c[] = new TestClass[20]. Now when I try b = (B[]) c, it gives doesn't compile saying incompatible types. Why are there different behaviors ?
@Shashwat You can assign a B[] instance to an A[] variable (just like you can assign a B instance to an A variable). Therefore casting an A[] variable to B[] (or an A variable to B) may succeed in runtime it the runtime types match. However, a TestClass[] can never be cast to B[], since TestClass is not a sub-class of B and B is not a sub-class of TestClass. That's why the compiler doesn't allow it.
Let me get this straight. Although you cannot do b = (B[]) a1;, b and a1 are compatible types and that is all the compiler looks for, so it compiles correctly, though it is actually impossible to assign b equal to a1. Please correct me If I'm wrong,.
@Shashwat b = (B[]) a1; could succeed in runtime if prior to this line you have a line that assigns an instance of B[] to a1 (for example a1 = new B[10];). The compiler doesn't analyze the runtime type of a1. It only analyzes its compile time type to determine whether the cast could succeed in runtime.
2

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.

Comments

0

You are right in saying "B IS-A A" and that is why
i) There is no issue when you put a = b;
ii) There is no issue at compile time for statement #3

But You can not say "A IS-A B", thus the run time exception.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.