• Post Reply Bookmark Topic Watch Topic
  • New Topic

Casting  RSS feed

 
Sam Samson
Ranch Hand
Posts: 63
IntelliJ IDE Java jQuery
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

It seems like I don't understand Casting.

Here my example:



Why in line 11 this is possible --> go2((Redwood) new Tree(), new Redwood()); ?

Isn't this a downcasting?
I understand that something like this is possible:
Tree tree = new Redwood();
Redwood redwood = (Redwood) tree;

But how do I have to read (Redwood) new Tree() ? I thought not every Tree has to be a Redwood, and thus this casting isn't possible, but it is. So I must have misunderstood something...

Enlighten me please


greez
Sam
 
Paul Clapham
Sheriff
Posts: 22818
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're right -- that cast isn't possible. But the compiler doesn't know that. All it knows is that you're trying to cast a Tree object to a Redwood reference. Doing that might be possible, so it doesn't complain. But you will get an error when you run the code.
 
Sam Samson
Ranch Hand
Posts: 63
IntelliJ IDE Java jQuery
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, so is it right that a cast is never possible on creating new objects? But why the compiler doesn't complain? I mean, what could happen between/before/during (?) the creating of the object that such a cast might ever be ok?
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The compiler doesn't try to work out where the object is coming from, or what it's exact type is. It just considers this as a cast from a Tree reference to a Redwood reference. And this might work. In this particular case it won't work, but as far as the compiler is concerned it might.

The compiler will only step in if the cast cannot possibly work based on the reference types. This generally happens when the types are in different branches of the inheritance tree. Try casting your newly created Tree object to a String, and the compiler will go "no, that cannot possibly work - you must have made a mistake".

Casting straight after creating the object is pointless - as you say, it shouldn't work. So avoid doing it. But there's a limit to how far the compiler will go in helping you not make mistakes.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sam Samson wrote:Ok, so is it right that a cast is never possible on creating new objects? But why the compiler doesn't complain? I mean, what could happen between/before/during (?) the creating of the object that such a cast might ever be ok?


No, it's perfectly legal. The rules for casting references are thus:

1) At compile time, it is only legal to cast up or down a single branch of the type hierarchy. So if D extends C which extends B which extends A, then something that is declared to be of any one of those types can be cast to any other of those types, because as far as the compiler is concerned, the actual runtime object *could* be of the type you're casting to. Even if you can see by the code that it won't be, the compiler doesn't care. It doesn't execute the code to see what will happen.

If there's some other type E, which is not in the A, B, C, D "subtree", then it is *not* legal to cast between E and A, B, C, or D, in either direction. That is (B)E and (E)B are both illegal. This is an error at compile time, because the compiler knows that something declared to be a B can never be an E, and vice versa.



2) Even if the cast succeeds at compile time, you can get a ClassCastException at runtime if the object pointed to is not of the appropriate type



 
Sam Samson
Ranch Hand
Posts: 63
IntelliJ IDE Java jQuery
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


The line Peach peach = (Peach) fruitLemon; throws a ClassCastException at runtime.

Is it true that the compiler looks only at the reference variable when casting, and not what object is really referenced?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sam Samson wrote:

The line Peach peach = (Peach) fruitLemon; throws a ClassCastException at runtime.


Right because the object that the fruitLemon points to is not a Peach, nor any subclass of Peach. As per my rule #2 above.

Is it true that the compiler looks only at the reference variable when casting, and not what object is really referenced?


Correct. As per my rule #1 above. Since fruitLemon is declared to be of type reference-to-Fruit, the compiler knows that it could point to a Peach object at runtime, and it trusts that you know what you're doing when you say, "I know that you only know this as a Fruit, but trust me, it will actually be a Peach."

Consider this:


If we wait until runtime to determine which class to instantiate, there's no way for the compiler to know what the object is, so it either has to allow that cast, meaning if we screw it up it's our own fault, or it has to disallow it, meaning a lot of code would get a lot harder to write. (And while there are cases where the compiler could theoretically tell what runtime object will be, the reasons why it doesn't do so boil down to, "It keeps the language rules and the compiler simpler."

And, after all, the whole point of casting is that it allows us to say, "I know better than the compiler," and then superseded some rules of the language's type system.
 
Sam Samson
Ranch Hand
Posts: 63
IntelliJ IDE Java jQuery
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sam Samson wrote:Thanks a lot


You're welcome!
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!