aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes ClassCastException versus a Inconvertible Types compiler error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "ClassCastException versus a Inconvertible Types compiler error" Watch "ClassCastException versus a Inconvertible Types compiler error" New topic
Author

ClassCastException versus a Inconvertible Types compiler error

Chad Michaels
Ranch Hand

Joined: Jun 25, 2010
Posts: 42
OK, for some reason, this one keeps giving me fits. And for obvious reasons, it could boil down to either an exam answer of "Compilation fails" or a "Runtime Exception". In short, is there any telltale way to determine 100% of the time which of the two problems will occur? I keep playing around with this one, but can't seem to get it straight in my mind. Sometimes I'm expecting one, but get the other... and vice versa. What's the deal???
Deepak Bala
Bartender

Joined: Feb 24, 2006
Posts: 6662
    
    5

A class cast occurs when you tried to cast something at runtime, whose type is not what you thought it would be. When you cast, you are telling the compiler - 'Hey compiler, case my Animal to Dog. I know that at runtime it could even be a Cat but I am pretty darn sure that we will get a Dog.' If at runtime the JVM finds that the Animal was say an Elephant, it will throw a ClassCastException.

In-convertible types is a scenario where the compiler knows for sure that the types in question cannot be converted. This is because they are no where near each others hierarchies. For example



Integers and String have no relation. The only have a common parent - Object. So the compiler knows there is no way this assignment will work. Also, you cannot cast this since the compiler *still* knows that it wont work.


SCJP 6 articles - SCJP 5/6 mock exams - More SCJP Mocks
Deepak Bala
Bartender

Joined: Feb 24, 2006
Posts: 6662
    
    5

oh and welcome to javaranch Chad
Chad Michaels
Ranch Hand

Joined: Jun 25, 2010
Posts: 42
Well thank you very much Deepak.... very nice of you

So, I read what you wrote, and I wanted to make things a bit more difficult to see. I don't think I accomplished my goal, but here is what I came up with. Let's say you have 3 classes, HumanTransporter, then class Car and class Boat both extend from it.

class HumanTransporter{ }
class Car extends HumanTransporter{ }
class Boat extends HumanTransporter{ }

...somewhere in main....
HumanTransporter ht = new HumanTransporter( ) ;
Boat b = new Boat( ) ;
// Car c = ( Car )b ; // If you UNcomment this line, it creates a compiler inconvertible types error.

ht = new Car( ) ;
Boat bb = ( Boat )ht ;

Now, what's special about this code I created? If you compile it without the commented lines, it will first give you an inconvertible types error due to the Boat and the Car. However, if re-comment the stated line, and get the code to compile, you then get a ClassCastException "Car cannot be cast to a Boat". BUT: This is my point! If the ClassCastException states the "car cannot be cast to a boat", why did this same infaction get caught by the compiler on the other line above?
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4421
    
    8

The difference is the reference type.

In the line you've commented out, b has the reference type Boat. So the compiler knows that b is a Boat. And since a Boat cannot possibly be a Car, the cast cannot possibly work.

In the later case, ht has the reference type HumanTransporter. Although you've assigned a Car to it, the compiler still thinks of it as a HumanTransporter. So it thinks the cast to a Boat might work, and allows it to compile. Then you get the exception when the VM realises it isn't a Boat.
Chad Michaels
Ranch Hand

Joined: Jun 25, 2010
Posts: 42
Thanks Matthew! That was a perfect explanation, and really helped clear it up for me!
Unmesh Chowdhury
Ranch Hand

Joined: Jun 20, 2010
Posts: 45
Matthew is correct. Actually, compiler always thinks about the reference variable type. And JVM thinks about the actual object type on the heap which is referenced by the reference variable, and it is true in the case of casting and runtime polymorphism.

Compiler throws inconvertible error for casting if there is no inheritance relationship between the specified references. In your case there is no inheritance relationship between the Boat and Cat, they are just peer to each other.

But, in the case of HumanTransporter and Boat there is an inheritance relationship between the specified reference types. Thus, compiler doesn’t throw the inconvertible error. In this latter case, JVM will throw a ClassCastException since HumanTransporter type reference variable doesn’t refer any Boat type or its subtype object on the heap at runtime to cast into Boat type.

M.Sc. in CS, OCPJP6 93%
Chad Michaels
Ranch Hand

Joined: Jun 25, 2010
Posts: 42
Unmesh, thanks for taking it further with the explanation. So from what I understand, the compiler just looks to see if the cast is possible (according to the hierarchy of the referency type and the cast type), and leaves it up to the JVM to check if the cast actually worked? If so, that makes it much easier to understand.
Smriti Lath
Greenhorn

Joined: Jun 21, 2013
Posts: 4
Hi,

Taaking the same issue further, in the following example why is a casting exception returned instead of a compile time error -



in this case neither class Boat nor its base class Transporter is related to the interface Drivable. Should this return a compile time error?
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9305
    
  17

If there are interfaces involved, then generally you can runtime exceptions instead of compile time errors. When you typecast from a class to an interface or from an interface to a class (non-final class to be precise), the cast is allowed at compile time.

Here (1) and (2) are allowed at compile time but (3) is not. This is because of the way the compiler works as everyone said, it looks at reference types. So the new Whatever part is only visible to the compiler at that statement not after that. So basically this is how the compiler looks at it

Now in this situation (1) and (2) are allowed because there might be a class ComplexClass extends PlainClass implements PlainInterface. So the compiler assumes pc and pi might be actual objects of that class. This is why these casts are allowed at compile time. For (3), there cannot be a class which extends both PlainClass and PlainInterfaceImpl so the cast can never succeed at runtime. This is why the compiler alerts you...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: ClassCastException versus a Inconvertible Types compiler error