casting example

Given the following classes which of the following will compile without error?

interface IFace{}

class CFace implements IFace{}

class Base{}


public class ObRef extends Base{
public static void main(String argv[]){
        ObRef ob = new ObRef();
        Base b = new Base();
        Object o1 = new Object();
        IFace o2 = new CFace();
        }
}
1) o1=o2;
2) b=ob;
3) ob=b;
4) o1=b;
I was going through above question from link

http://www.jchq.net/certkey/0501certkey.htm

I have not understood the answer which says 1, 3, 4. I was not clear on what we can assign to what and moving up, down the parent, child class assignment.


 Any ideas, resources,sample code,links,  highly appreciated. thanks in advance.
LVL 7
gudii9Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

for_yanCommented:

Actually correct answer in my mind is 1,2,4 will compile, but not 3

(1) o1 is declared as Object
therefore you can assign to o1 instance of any class, as all classe
in java inheriit  from Object

(2) b is declared as Base; Obref,which inherits from Base, is in fact also
and instance of base - this is OK assigmnement

(3) ob is declared as ObRef and b is Base, there is no guarantee
that b is instance of ObRef - this is incorrect assignemnt; it requires explicit cast
to be acceptable like ob = (ObRef) b;

(4) o1 is Object, therefore can reprsent an object - see explanation for item  (1)

If class A extends class B - you can think of class A as being more
complex than class B. It in fact means that class A has more details,
thefore instance of class A will always also be instance of class B, but only some
instances of class B will be instances of class A.






 

0
theKashyapCommented:
You can catagorize the casting here in two types:
Upcasting:
- Where you cast an object instance to one of it's parent/base types.
- This can be implicit or explicit.
- This is always allowed. 1, 2 & 4 are all upcasting so they work.
- As Object is base class of ALL, any instance of any class can be assigned to a variable of type Object, so #1 & 4 are valid.
- As Base is a base/parent class of ObRef #3 is valid
Downcasting:
- Where you cast an object instance to one of it's child/derived types.
- This has to be explicit. Else it's a compiler error.
- As the compiler doesn't (always) know whether the object instance being downcast'ed is actually of the type being casted to, you might get a ClassCastException at runtime.

See this link for some example.

In case you donno:
// Implicit casting:
o1 = o2;
o1 = b;
// Explicit casting,
// - here the first one would compile but will throw ClassCastException when you run it.
// - second one is a valid upcast, so need not be explicit.
b = (Base) ob;
o1 = (Object) b;

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gudii9Author Commented:
>>>As the compiler doesn't (always) know whether the object instance being downcast'ed is actually of the type being casted to, you might get a ClassCastException at runtime.

can you please elaborate o this.
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

for_yanCommented:

It means that when you are downcasting (say ObRef extends Base - now you have object "b" of type Base
and you use cast to assign it to variable of type ObRef, like

ob = (ObRef) b

Compiler will alow you to compile it becuse it does not know - perhaps
in fact you "b " object was initially created as ObRef, as say ObRef ob1 = new ObRef(); and then
sometime  later in its life it was assigned to varaible b of type Base; so compiler will allow it
but at Runtime jvm will check and  if it discivers that  b was created as Base and never
was ObRef - it wil throw ClassCastException


0
for_yanCommented:

you may think of it in such way - one guy in his program deals with different sorts
of objects - all of them of the type Base, but some of them were of more sophisticated type ObRef,
but this guy does not care - for his operations it is just important that all of them are base type objects

then this guy passes you the stream of succh objects into your program and he labels all of them
as Base objects - because it is correct and it is simpler for him

then you in your program want to work in different way with those which are simple Base, and those
which have additional properties of ObRef - you can try to cast all of those objects to ObRef -
and at this moment Java will execute the cast if you apply it to those of the  objects
whaich were  originally created as ObRef but it will throw exception
if it was originally created as Base and not as Obref.

in such situation instanceof operator will be handy (remember that operator?)- you can first
check if your next object is instanceof ObRef or not. if it is instance of ObRef then you should
not be afraid to cast it to ObRef. if instanceof ObRef returns false, then you
should not cast this object to ObRef, as this is a simple Base type object, and  such cast will cause Exception

this is in fact quite common situation because that guy who gives you these objects
could have received them from someone else and his operations did not deal
with special propertiies of ObRef - he did not care, for him it was enough
that they all have properties of Base, and ,as you perform some more
sophisticated operations, this distinction may be critical for you in your code.
 



 
0
gudii9Author Commented:
>>o1=o2;

you can question like o2 is o1 and if true i can go ahead and assign right. please advise.

like Ford is a car
or

toyota is a car
0
for_yanCommented:
yes, if o1 is more general than o2 (mweaning that o2 inherits from o1) you can
assign directly  

o1 = o2;

if o1 is less general than o2 (meaning that o1 inherits from o2) than
you need to use cast

o1 = (O1) o2;

and then at runtime JVM will know
if o2 instance was indeed created as o1 it will allow it,
otherwise it will through CastClass exception




0
gudii9Author Commented:
so upcasting with respect to object is implicit or optional i mean when you assign child class instance to parent class object instance.

Whereas with primitives it is reverse scenario i observed.Where
if you assign bigger datatype to small datatype then you need to do explicit casting. Say

int i;
long l;

i=(int)l;

 please advise
0
for_yanCommented:

I would not necessarily compre in this way - in fact situation is rather similar than opposite

Let's look first at objects:

so if you have class Car and class Ford which extends Car

So compiler knows that Ford extends Car

Therefore if you state that you want for some purpose
at the certain stage of life of the instance of class Ford
you want for some time to look at this instance as of the instcne of Car,
the compiler has no doubts about it - all instances of Ford at the same
time are instances of Car, because compiler read in the
header of your Ford class that it extends Car.
So compiler does not need any additional confirmation from you, the programmer.

When you do opposite thing - you have an instance
of Car and you are telling the compiler that you want to llok at this Car
as the instance of Ford. You, the programmer, perhaps know about this instnace
something more than knows compiler, and in particuler you know that
in fact this car is ford, so compiler requires that you communicate
this knowledge to the compiler and additionally confirm with explicit cast.
This is a precaution compiler takes to make probability of your mistake smaller.

At the runtime JVM can already check if this instance is in fact Ford (and has additional properties, which
general car does not have) and if at runtime it encounters situation
that you want to think about toyota as if it if ford - then JVM will throow exception.
Compiler is not that smart - it does not have this whole instance to inspect,
this instance at runtime may in fact will be sent from another library class
to which compiler does not have access at compilation time - that's
why compiler, in fact as a warning to you, the programmer,
requires that you use explicit cast.

More or less the same logic applies to primitives.
When you assign integer to long variable
then compiler knows that any integer will fit into long
then no cast is necessary.
If you want to do opposite, then the same thing
there can be a long value that cannot fit into integer
and compiler not knowing it wants your confirmation (explicit cast).
So logically situation with objects and with primitives is similar.

When compiler cannot be sure - it requires confirmation of the programmer -
explicit cast.












 










0
gudii9Author Commented:
>>if o1 is less general than o2 (meaning that o1 inherits from o2)

i am thinking it is other way in my mind.

Ford is more specific and has more specific features like transmission, breaking, seating system compared to car right. which means ford is less general than car. which means o2 child class objcet instance is less general than o1 super class object instance.


>>>When you do opposite thing - you have an instance
of Car and you are telling the compiler that you want to llok at this Car
as the instance of Ford.


means

Car c;
Ford f;
f=(Ford)c

>> llok at this Car
look means i need to visualize from right to left side of the equality sign
0
for_yanCommented:

>>if o1 is less general than o2 (meaning that o1 inherits from o2)

You say you are thinking the other way but you write in fact iin the same way

if o1 is Ford and o2 is Car then substituting:

   if Ford is less general than Car (meaning that Ford inherits from Car)

I guess you will agree with this - and I just replaced o1 wit Ford and o2 with Car


When  I say compiler needs to look at this Car as an instance of Ford
I do not mean "visualize",

I mean that when compiler encounters f=(Ford)c
 it means that next time when it encounters some method exceuted on f
which is specific for Ford - this method should be able to execute.
Compiler knows that in general case mot all instances of Car would behave
as instances of Ford, therefore it requires from you the programmer cconfirmation
that you intentionally do this assignemnt, and you can do it
because you have some considerations (not known to compiler at this moment,
but known to you the programmer) that at runtime it would never
happen that instance  c would happen to be not an instance of Ford.
(maybe you have some if's above that you insured it, but compiler
at comipile time does not execute the whole of your code, so
it cannot percieve this logic and it needs to rely on your opinion).

In the opposite situation it(compiler) does not need any confirmation,
as all instances of Ford are instances of Car, and there is no need to worry that
some method of Car will not execute on Ford instance.

Seems quite clear to me; let me know if you want more explanation.

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.