• Post Reply Bookmark Topic Watch Topic
  • New Topic

Objects/Casting/References ~confused~  RSS feed

 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

I have been trying to wrap my head around the idea of casting objects (when to use it and why/ what is okay, what is not).

I have looked up several articles and coded around but for some reason it isn't clicking.



I don't understand the difference between:

Animal f = new Fish();

and

Fish f = new Fish();

When calling on them they both seem to reference the Fish class. So what is the difference?




If you could point me to an article that can really dumb this down or explain it in very simple terms I will be very appreciative. I have tried so hard to understand but once I think I have it I realize I don't!



 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think that sometimes when you go and ask someone for help you tend to begin understanding by listening to yourself ask the questions. I seem to be getting traction on this now but still only traction. I feel I was over-thinking it.


However, it would still help to have an explanation (or link to good explanation)
 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So I THINK that I understand this:

Animal f = new Fish();

and

Fish e = new Fish();



f is of Type Animal- and it points to a Fish which is okay because a Fish is an Animal.

e is of Type Fish - and points to a Fish object.

Even though f points to a Fish object, the compiler does not know that it just sees that it is an Animal Type and it gives a compilation error.
however, you can tell the compiler that you swear f points to a fish object and it believes you, compiling with no problem.
 
Arthur Vinicius Rebelo
Ranch Hand
Posts: 30
1
Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Take a look at this:


Now instantiate:


You can't call a.swim() because although a references to a Fish object the variable type is Animal. And Animal only knows from breathe() method. That's why we need cast, so the casted object behavies like the cast Class

So lets create a new variable type Fish from the cast of a:


b as you know references to the same object but behavies like a Fish

Now you can do this b.swim();

I think you should begin with primitive types casts. Here
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jacob

Assuming that Fish is a class that extends a class called Animal or implements an interface called Animal then the code you posted would not need casting. You only need to cast if you have a reference that is declared as a supertype but you want to treat it as a subtype (and access methods from the subtype, as Arthur showed you).

However, in general if you find yourself needing to make casts like that then you probably have a problem with your design. Certainly in the code I write there are very few places where I would use an explicit cast like that.
 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


The reason I wanted to understand it because there are a few questions on Oracle's exam that require this understanding.

THANKS for the link. I will look at some more basic casting.

I feel that I am starting to understand it. So I tried to translate the code into human language to confirm that I am getting it:

(assuming fish extends animal)

Fish x = new Fish(); // my name is x, I can take you to a fish.

//Animal y = x; // my name is y and I can also take you to x's fish.
// compiler: I can see that you represent an Animal which is great, but how can I trust that you will actually take me to a Fish?
// I will not allow this because you did not promise me you will take me to a fish.

Animal y = (Fish)x // Okay compiler, I promise you that I am going to take you to a fish
// compiler: Ok, I believe you. However, if this program runs and I find out you do not take me to a fish, I'm going to give you an error.


 
Tony Docherty
Bartender
Posts: 3271
82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yep you've got it.

The only thing I would add is for the cast to get past the compiler the thing you are casting from and to have to be compatible types ie one has to be a subclass of the other.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jacob Draper wrote:

Fish x = new Fish(); // my name is x, I can take you to a fish.



So far so good

Jacob Draper wrote:
//Animal y = x; // my name is y and I can also take you to x's fish.
// compiler: I can see that you represent an Animal which is great, but how can I trust that you will actually take me to a Fish?
// I will not allow this because you did not promise me you will take me to a fish.


No, the compiler would not have any problem with that line (given the assumption that Fish extends Animal). All Fish are Animals, and can always be assigned to an Animal reference. 'x' is of type Fish, so the compiler will happily let you assign it to y (type Animal).

It is the opposite scenario that the compiler will not allow:

Jacob Draper wrote:
Animal y = (Fish)x // Okay compiler, I promise you that I am going to take you to a fish
// compiler: Ok, I believe you. However, if this program runs and I find out you do not take me to a fish, I'm going to give you an error.


That cast is unecessary. 'x' is declared as being of type Fish, so the compiler already knows its a Fish. The cast you have here will not do anything.

It is the opposite scenario that the compiler will not allow. It will not allow you to assign a supertype reference to a variable declared as a subtype. In general, all subtype instances are also supertype instances, but not all supertype instances are subtype instances. So for example all men are human, but not all humans are men. All cars are vehicles, but not all vehicles are cars etc.

 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I think you should begin with primitive types casts. Here


Thanks Arthur, great link!



Mike, Thank you for correcting me. I had it in my head right but wrote it out wrong.

I should have done something like,

Animal x = new Animal();
Fish y = Fish();

x = y;

y = (Fish)x // compiler sees x is of type animal, and you promise it will take you to a fish

Had it down backwards, but I am now understanding which is relieving.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arthur Vinicius Rebelo wrote: . . .

I think you should begin with primitive types casts. Here
Disagree. There is a world of difference between casting primitives, and casting object references.
In the case of primitives, the type conversions (which are not well explained in the link you gave) alter the actual value of the variable. They are also always feasible, albeit at the risk of obtaining an unexpected result, even from the widening conversion in line 3:-In the case of reference types, you are only altering the type of the reference and can neither change the value nor the type of the object pointed to. They may not be feasible, causing Exceptions.Agree with Mike Thompson: using casts would cause me to doubt the design. Whenever you have class XYZ extends PQR and you are adding non‑private methods or any fields, think again; there may be a better way to do it.
 
Arthur Vinicius Rebelo
Ranch Hand
Posts: 30
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Disagree. There is a world of difference between casting primitives, and casting object references.


I got your point, they aren't exactly the same thing. But if the OP doesn't know much about casting shouldn't he go for primitive types casts first ?

Agree with Mike Thompson: using casts would cause me to doubt the design.


Surely does, but I think in this context it's just premature optimization cause the OP is just trying to learn about casting. Are you think ?

Anyway thanks for the hint !
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The OP is trying to learn about casting, but they also wanted to know when to use it. I just wanted to make sure they know that casting references is generally bad practice.
 
Jacob Draper
Ranch Hand
Posts: 35
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Surely does, but I think in this context it's just premature optimization cause the OP is just trying to learn about casting


Yes, just learning this to pass Java Associate exam. Thanks for all of your help everyone! I have learned a lot today.
 
Arthur Vinicius Rebelo
Ranch Hand
Posts: 30
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The OP is trying to learn about casting, but they also wanted to know when to use it. I just wanted to make sure they know that casting references is generally bad practice.


Yeah you are right. I might misunderstood when he asked when to use. I thought he was asking when he needs to call for a cast not when is a good practice to do.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arthur Vinicius Rebelo wrote: . . . But if the OP doesn't know much about casting shouldn't he go for primitive types casts first ? . . .
I think it is unfortunate that the same word ℌcasting” is used for primitive conversions and reference type conversions, because the two actions are so different. You cannot learn about casting references by casting primitives, and vice versa.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!