About Question enthuware.ocajp.i.v7.2.951 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
javaman
Posts: 33
Joined: Wed Nov 13, 2013 4:11 pm
Contact:

About Question enthuware.ocajp.i.v7.2.951 :

Post by javaman »

Hello,

In this example:

Super s1 = new Super(); //1
Sub s2 = new Sub(); //2
s1 = (Super) s2; //3

I see that a reference variable of a superclass (s1) can point to an instance of a subclass (s2) of that variable. But when should I take into account the rule that says "you can only cast a ref. variable 'a' to a ref variable 'b' when 'a' is actually pointing to an instance of 'b'"???

As in this example :
class Super{}
class Sub extends Super{}

if I do:
Super s1 = new Sub(); //1
Sub s2 = (Sub)s1; //2

I can cast s1 to s2 because it is pointing to an instance of s2

So: why in this question can I cast s2 to s1 while s2 is not pointing to an instance of s1?

Thanks for your reply

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by admin »

Explicit casting is checked in two stages - first at compile time and second at run time.
1. At compile time, the compiler only checks if it is possible for a reference to point to an object of the class given on the left hand side i.e. the class you are trying to cast it to. In the above case, Sub s2 = (Sub) s1; is valid at compile time because it is possible for s1 to point to an object of class Sub. Compiler cannot check actual object. It just checks the possibility.

s1 = (Super) s2; //3
THis is valid at compile time because the reference type s2 is of class Sub, which IS-A Super. So it is fine even without an explicit.

2. At run time, the JVM checks if the actual object being pointed to by the references is of the same (or sub) type of the class on the left side. If not, then a ClassCastException is thrown.In the above case, s1 does indeed point to an object of class S2. So the JVM is ok as well.

s1 = (Super) s2; //3
THis is valid at run time because s2 is pointing to an object of class Sub, which IS-A Super.



BTW, your question, "why in this question can I cast s2 to s1 while s2 is not pointing to an instance of s1?" doesn't make sense. There is nothing like instance of a reference. You should ask, "Why in this question can I cast s2 to s1 while s2 is not pointing to an instance of Super"? A reference is always to an instance of a class (not to an instance of another reference). Here, s2 is a reference of class Sub, not of s1.

Why do you think that s2 is not of type Super?

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

javaman
Posts: 33
Joined: Wed Nov 13, 2013 4:11 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by javaman »

Ok...let's see if I get it...

Because Class Sub is-a Super, any variable of type Super can point to an instance of class Sub. The cast to Super (s1 = (Super) s2;) in the question is unnecessary. In the question I can have s1 refer to s2 even if s2 is not pointing to an instance of s1 because s2 is-a Super. Like you don't explicitly have to transform a cat, dog, horse to an animal because they _are_ animal already.

like this:

Code: Select all

class Animal{}
class Dog extends Animal{} // a dog is-a animal
Animal ani = new Animal();
Dog dog = new Dog();
ani = dog; //ani can point to dog even if dog is not pointing to an instance of animal
                //because dog is-a animal
on the other hand...

If I want to have a reference of type s2 point to in instance of s1 (saying something like 'this animal is a dog') I have to cast s1 to s2 (to bypass compiler) _and_ make sure that at runtime s1 is indeed pointing to an instance of class s2.
It's like saying 'This animal is a dog' and since an animal can be anything, I have to make sure that during runtime the animal I refer to is indeed pointing to a dog and not to a cat, fish or horse.

like this:

Code: Select all

class Animal{}
class Dog extends Animal{}
Animal ani = new Dog(); //this animal is a dog
Dog dog = (Dog)ani; // tell compiler this animal is a dog.
works because ani actually points to an instance of Dog.

Or

Code: Select all

class Animal{}
class Dog extends Animal{}
Animal ani = new Animal();
Dog dog = new Dog();
ani = dog; // make var ani point to an instance of Dog. Works because a dog is an animal
Dog dog2 = (Dog)ani; // tell compiler this animal is a dog.
works because of the line ani = dog; - ref variable is pointing now to an instance of Dog so it can be cast to Dog and referred to by a var of type Dog.

Phew... Now I must succeed for these casting questions.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by admin »

You got it :)
If you like our products and services, please help us by posting your review here.

suyashgulati
Posts: 1
Joined: Thu Jan 08, 2015 5:09 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by suyashgulati »

can you please tell me the need for explicit casting, even if its not necessary.

also tell me rules when will the casting cause errors.

jwitt98
Posts: 3
Joined: Thu Aug 04, 2016 10:40 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by jwitt98 »

Am I correct in saying that an explicit cast to (Super) is not require in this case?

Code: Select all

class Super {  }
class Sub extends Super {  }
public class Test{
   public static void main(String[] args){
      Super s1 = new Super(); //1
      Sub s2 = new Sub();     //2
      s1 = s2;        //3
   }
}

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by admin »

What happened when you compiled it?
If you like our products and services, please help us by posting your review here.

mihhay
Posts: 10
Joined: Wed May 09, 2018 12:48 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by mihhay »

Code: Select all

class Animal {}
class Dog extends Animal {}

public class TestClass {
	public static void main(String[] args) {
		Animal a1 = new Animal(); 
		Dog d2 = new Dog();
		
		a1 = d2;        //1  a1 is taking the reference of d2 ? is this assumption 
                                     //wrong? or how you "read" / what means a1=d2 ? 
		a1 = (Dog)d2;   //2
		a1 = (Animal)d2;//3
		
		d2=a1;     //4  indeed if I run it, I will get "Exception in thread "main" 
                                //java.lang.Error: Unresolved compilation problem: 
		                 //Type mismatch: cannot convert from Animal to Dog" 
		                    
	}
}
1) I have difficulties to understand on what line it will apply the IS-A statement ? at line 2 or 3 ? ( Dog "IS-A" Animal) . Also at what line we can say Animal is a Dog ( let's say we do not have just this context, and we do not consider a "Cat" as an another "Animal").
I understand your point here" But an Animal may not always be a Dog. " but let's say in this context Animal is always is a Dog , or this assumtion is wrong? I know that Cat is also an Animal, but I want to understand the IS-A concept.

2) Is it redundant to say a1 = (Dog)d2; //2 ?

3) At line //4 why I do not get a ClassCastExpection ?

Thank you!

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by admin »

I think you are confused because you are mixing two different things - compilation and execution. Compiler does not know about the actual objects to which a variable points because objects are created only when the program is executed i.e. at run time. Compiler only knows about the type of objects to which a variable will point to (i.e. later at run time). So for example, if you have Animal a; then compiler does not know what exact type of object a will actually point to at run time. It only knows that whatever object a points to, that object will satisfy the is-a test with Animal. In other words, the compiler knows that that object will be an Animal. The compiler understands that that object could be a Dog also or any other subclass of Animal.

1. IS-A check is applied by the compiler at every assignment using the information that is available at compile time. If you have a statement x = y, then the compiler checks whether type of y is-a type of x. It allows compilation only if type of y is-a type of x.

So in your code above, in all these statements such as Animal a1 = new Animal(); , Dog d2 = new Dog();, a1 = d2; the compiler checks whether the type of the variable on right hand side of equals IS-A the type of the variable on the left hand side of equals.

Thus, Animal a1 = new Animal(); works because Animal satisfies the is-a test with the type of variable a1, which is Animal.

Similarly, a1 = d2; , the type of d2 is Dog and the type of a1 is Animal. Since Dog is-a Animal, this assignment is ok.

2. Yes, the cast in the statement a1 = (Dog)d2; is always redundant because d2 will always point to a Dog and since Dog is an Animal, it is ok to assign a Dog to a1, which is of type Animal. The cast in a1 = (Animal)d2; is also redundant for the same reason.

These statements show that a1 can point to a Dog object also but not necessarily always.

Therefore, the statement d2=a1; may not always work at runtime because what if a1 points to a Cat? The JVM will not allow the variable d2, which is of type Dog to point to a Cat! To prevent such exceptions at run time, the compiler does some basic checks while compiling the code itself. It cannot prevent all wrongful assignments but tries to do its best based on the information that is available at compile time.

So in this case i.e. d2 = a1, compiler wants assurance from the programmer that a1 will point to a Dog at run time. The programmer knows the code that he has written so he is able to assure the compiler by "casting" a1 i.e. d2 = (Dog) a1; Now the compiler is ok. It means that the compiler is not sure whether a1 will point to a Dog or not at run time but since the programmer is guaranteeing that, the compiler compiles the code.
If you like our products and services, please help us by posting your review here.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by admin »

3. There is no ClassCastException at //4 because a1 does point to a Dog object at run time as per the code that you've written. Why do you think there should there be a ClassCastException? CCE will be thrown by the JVM only if your guarantee turns out to be false i.e. only if a1 does not point to Dog.
If you like our products and services, please help us by posting your review here.

mihhay
Posts: 10
Joined: Wed May 09, 2018 12:48 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.951 :

Post by mihhay »

"For example, a Dog  "IS A" Animal, so you don't need to cast it. But an Animal may not always be a Dog. So you need to cast it to make it compile and during the runtime the actual object referenced by animal should be a Dog  otherwise it will throw a ClassCastException."

Reading this I was expecting to see ClassCastException...

I really really appreciate your wonderful explanation! Thank you!

Post Reply

Who is online

Users browsing this forum: No registered users and 70 guests