• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

When class casting should output runtime exception and when it should output compiler error

 
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am having trouble understanding when class casting ends with a compiler error or the runtime exception ClassCastException . From what i understand each time the object referencing variable or object being cast is not on the same inheritance line to the class being cast (aka it's impossible for them to have an inheritance relationship) the code it will result in a compilation error . But when the variable or object can have an inheritance relationship with the class being cast but the IS-A check between the object or the variable that references an object and the class being cast to fails a run time exception ClassCastException is thrown .

But then i don't understand why this code does not have compile errors but just throws ClassCastException at runtime :



What am i not understanding correctly ?
 
Tiberius Marius
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Or saying it in another way i have trouble understanding why the first code section throws ClassCastException while the other will not compile .





 
Marshal
Posts: 80665
478
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Because the compiler only compiles the code and does not run it, it does not remember what was added to the List. It simply knows the List contains <Ink> which might be a valid candidate for the cast.
In the second case, the compiler can “know” that the black ink cannot be in the List, so the cast is bound to fail.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:In the second case, the compiler can “know” that the black ink cannot be in the List, so the cast is bound to fail.


That doesn't explain the first scanario though (in the OP), which, I have to admit, I find a bit mystifying too.

BlackInk is plainly NOT a Printable, by definition; so why does the compiler allow the cast?

I have to admit, I'm taking Tiberius' word for it though, 'cause I'm too lazy to test it for myself.

Winston
 
Campbell Ritchie
Marshal
Posts: 80665
478
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I couldn't understand the first case either.
 
Tiberius Marius
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Because the compiler only compiles the code and does not run it, it does not remember what was added to the List. It simply knows the List contains <Ink> which might be a valid candidate for the cast.
In the second case, the compiler can “know” that the black ink cannot be in the List, so the cast is bound to fail.



About the code at the first post , i did try to run it and indeed it throws a ClassCastException . I don't understand why but then again i m not sure i understand why the code in the second post does not compile despite your explanation. The books i use funny enough don't really focus that much on casting so please correct me if i m wrong :

When i cast an object or object referenced by a variable to another class the following happens :

The compiler looks to see if the object declared type and the Class to be cast-ed to are on the same inheritance line ( aka fruit - apple - golden_delicous and not for example apple and orange to make possible an IS-A relationship between the object and the Class) .If inheritance relationship between those two is not possible a compiler error will result . If it is possible at runtime the object is checked in an IS-A relationship to the Class to be cast-ed . If it's not( the object does not contain an instance of the class to be cast-ed to) a ClassCastException is throwned .If it is the object declared type becomes the class used for casting .
 
Bartender
Posts: 322
24
Eclipse IDE Firefox Browser
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm also going through Mala's book and I had trouble with that concept, too.

I found Henry Wong's answer from a few years back:
https://coderanch.com/t/587625/java/java/casting#2675659

As I understand Henry's answer, the compiler is open to the possibility that another class extends BlackInk and implements Printable, which would make the IS-A relationship true.
This will compile and not throw a ClassCastException:

However, changing BlackInk to a final class eliminates the possibility of extension and would now generate a compilation error. When BlackInk is final, the compiler will “know” that there is no possibility of a derived class that implements Printable.

Cheers!
Chris
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tiberius Marius wrote:If inheritance relationship between those two is not possible a compiler error will result...


And that's what I find odd about your first post. BlackInk is not a Printable, yet it allows the cast - I have tested it now - indeed, I can even write:
printable = (Printable) new Object();
which just seems plain wrong to me.

Buck your ideas up, javac.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chris R Barrett wrote:As I understand Henry's answer, the compiler is open to the possibility that another class extends BlackInk and implements Printable, which would make the IS-A relationship true.


Ah, of course! Well done Chris; cow for that.

It still doesn't explain allowing
printable = (Printable) new Object();
though. To me that IS wrong.

Winston
 
Chris Barrett
Bartender
Posts: 322
24
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:Well done Chris; cow for that.


Thank you so much! I feel like I just stole Henry Wong's cow, so feel free to give it to him. I just found and interpreted his response.
Mind you, the handle "cattle rustler" instead of "ranch hand" would be kind of cool...
 
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well certainly in the general case the compiler cannot know the runtime type of an object. I guess the compiler designers decided not to bother tracking the runtime type even in the specific cases when it is known.

Printable p = (Printable) new Object();

could be re-written as

Object o = new Object();
Printable p = (Printable) o;

The compiler could still know the cast could fail in the second case (even if there where statements between those two), but it's generally accepted that this doesn't compile.
 
Master Rancher
Posts: 5161
83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike. J. Thompson wrote:Well certainly in the general case the compiler cannot know the runtime type of an object. I guess the compiler designers decided not to bother tracking the runtime type even in the specific cases when it is known.


Actually, the language spec prohibits the compiler from rejecting a program based only on knowledge of the runtime type of an object. Only the declared type of the reference may be considered. They didn't want it to be a crap shoot as to whether or not your program compiles, based on which version of compiler you got.

Mike. J. Thompson wrote:Printable p = (Printable) new Object();

could be re-written as

Object o = new Object();
Printable p = (Printable) o;

The compiler could still know the cast could fail in the second case (even if there where statements between those two), but it's generally accepted that this doesn't compile.


Did you mean, generally accepted that it does compile? Because it does. It also throws a ClassCastException at run time, of course. A smart compiler could figure this out and issue a warning - but it's not supposed to prevent you from being able to compile it.
 
Campbell Ritchie
Marshal
Posts: 80665
478
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One of the principles about compiler writing is that there are things which cannot be checked readily and reliably until runtime. So those things have to pass compilation, but may fail with Exceptions at runtime.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Indeed that's exactly what I meant. Thanks.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Actually, the language spec prohibits the compiler from rejecting a program based only on knowledge of the runtime type of an object. Only the declared type of the reference may be considered.


Yup. It makes sense. Thanks guys, one and all; I had a feeling I was missing something important from the OP; and of course it was that final qualifier (or rather, lack of it) - probably because, in true "paranoid programmer" fashion, I almost always make my classes final.

Winston
 
Tiberius Marius
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have to ask because no one replayed on it specifically and i m not sure it's 100% right , it's my view on casting correct ? And if not what the correct version ?

"The compiler looks to see if the object declared type and the Class to be cast-ed to are on the same inheritance line ( aka fruit - apple - golden_delicous and not for example apple and orange to make possible an IS-A relationship between the object and the Class) .If inheritance relationship between those two is not possible a compiler error will result . If it is possible at runtime the object is checked in an IS-A relationship to the Class to be cast-ed . If it's not( the object does not contain an instance of the class to be cast-ed to) a ClassCastException is throwned .If it is the object declared type becomes the class used for casting . "
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tiberius Marius wrote:I have to ask because no one replayed on it specifically and i m not sure it's 100% right , it's my view on casting correct ? And if not what the correct version ?


You're basically correct; and you ARE correct if the type you're casting to is a class. But if it's an interface (as with your cast to Printable), and the declared type of the variable is not final, then the compiler assumes that any subclass of it could implement that interface.

Does it make sense now?

Winston
 
Tiberius Marius
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

Tiberius Marius wrote:I have to ask because no one replayed on it specifically and i m not sure it's 100% right , it's my view on casting correct ? And if not what the correct version ?


You're basically correct; and you ARE correct if the type you're casting to is a class. But if it's an interface (as with your cast to Printable), and the declared type of the variable is not final, then the compiler assumes that any subclass of it could implement that interface.

Does it make sense now?

Winston



Yes , the part with the interfaces i ve understood from your earlier posts , i wasn't sure my view of casting is correct . Thanks for clarifying that .
 
Campbell Ritchie
Marshal
Posts: 80665
478
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I presume you are using this thread to find out why casting is often such a bad idea.
 
Tiberius Marius
Ranch Hand
Posts: 115
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's required for both OCA exam and generics and i imagine for many other things so i have to iron it out
 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So, my answer B was right even-though, according to Mala Gupta, the right answer should be D.


a printable = (Printable)blackInk will throw compilation error.
b printable = (Printable)blackInk will throw runtime exception.
c printable = (Printable)blackInk will throw checked exception.
d The following line of code will fail to compile:
printable = blackInk;
 
Chris Barrett
Bartender
Posts: 322
24
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Georges,

Welcome to the Ranch!

Hmmm... You sure the text says only D was the right answer? My book says B & D is the correct answer.
And D, as written in her question, is correct and will cause a compile time failure.

My question to you is why? Look closely at the code used in answer D.
(With only 107 seconds per question, it's easy to skim over such differences and not notice them. It's important you train your mind as the exam will expect you to spot subtle changes right away).
 
Georges VanH
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chris R Barrett wrote:Hi Georges,

Welcome to the Ranch!

Hmmm... You sure the text says only D was the right answer? My book says B & D is the correct answer.
And D, as written in her question, is correct and will cause a compile time failure.

My question to you is why? Look closely at the code used in answer D.
(With only 107 seconds per question, it's easy to skim over such differences and not notice them. It's important you train your mind as the exam will expect you to spot subtle changes right away).




Hi Chris,

You are right.
I did not notice it.
I will pass my exam tomorrow and Exceptions... Im getting kinda stressed out
 
Chris Barrett
Bartender
Posts: 322
24
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Georges VanH wrote:I did not notice it.


No problem - good luck on the exam!
 
reply
    Bookmark Topic Watch Topic
  • New Topic