Given: Sour extends Blue extends Pan

Pan p4 = new Sour();

Then set of 6 new statements given and asked to choose which ones will compile. They are:

  1. Pan p5 = p4;
  2. Pan p6 = (Blue)p4;
  3. Blue b2 = (Blue)b4;
  4. Blue b3 = (Sour)p4;
  5. Sour s1 = (Blue)p4;
  6. Sour s2 = (Sour)p4;

Answer: 5th one won't compile. Rest all will compile and run without exception.

Doubt: As a beginner I have understood that LHS should be usually a super class and RHS should be subclass if downcast not required like shown in original statement Pan p4 = new Sour();
I want to further understand on what basis the options are correct or wrong. For instance (1) is correct since p4's object type is still a sub of Pan so assignement is valid. I did not understand for rest. What is checked at compile time and runtime to consider them valid. As in what is matched with what for compile and runtime?

Thanks.

I read the document. But couldn't understand :( Anyways thanks for the help :)

Yes, it's not easy to read, but it is the only definitive answer!

Here's a crude summary of the key points for casting reference types, but I do mean crude, so see the JLS for the exactly correct version:

  • Compile-time checks are based on the declared types of the variables. Runtime checks are based on the actual type of the actual object.
  • casting or assigning a subclass to superclass is always OK, it's checked OK at compile time, no runtime checks needed.
  • assigning a superclass to a subclass (without a cast) is always wrong, and is rejected at compile time
  • casting a superclass to subclass may or may not be OK, it must be checked at runtime to see what the actual class of the object is. Then it may be OK or it may throw an exception
  • if the classes are not related by inheritance the cast is always invalid and errors at compile time

In case 5 the cast to a subclass may or may not be OK, so it will be checked at runtime. Because the object is a Sour it's also a valid Blue and the cast will be found to be OK. But the assignment of a Blue to a Sour is not valid without an explicit cast and is rejected at compile time.

Sorry of that's a bit garbled - it's late here - but with that overview maybe you can now revisit the JLS?

Gee thanks James :) Appreciate the help again :) Going through it now

I learnt (albeit unsuccessfully) that object type is compared with something at runtime. What is that? If it is an object type, then given above, variable p4's object type is Sour but what is the object type of p6/b2/b3/s1/s2 that is "compared" with p4's to avoid ClassCastException?

p6/b2/b3/s1/s2 are not objects, they are reference variables, and their type is fixed when they are declared. They haven't been initialised, so they don't have a object to refer to. Think about his example:

 Pan p4 = new Sour();
 Blue b2 = (Blue)b4;

(Blue)p4 cannot be known as definitely OK or not OK at compile time. p4's type is Pan, so the object it refers to may, or may not, be a Blue. So that has to be checked at run time.
At run time the actual object referred to by b4 is used, it's found to be a Sour. Sour is a subclass of Blue, so the cast is valid, and b2 can be set to refer to the same Sour object.

This question has already been answered. Start a new discussion instead.