This week's book giveaway is in the OCPJP forum.
We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes Please explain these answers Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Please explain these answers" Watch "Please explain these answers" New topic
Author

Please explain these answers

Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
In one of Marcus Greens mock quizes for Java Cert, a question is

What will happen if you attempt to compile and run the following code?
class Base {}class Sub extends Base {}class Sub2 extends Base {}public class CEx{ public static void main(String argv[]){Base b=new Base();Sub s=(Sub) b; }}
1) Compile and run without error
2) Compile time Exception
3) Runtime Exception

I say its #1, because the cast is used to fit a super class into its subclass. But the answer he gives is #3. I dont understand why.


May the force of the Java be in all of us !!!
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2854
    
  11

You can always upcast, that is cast from a subclass to a superclass. When you downcast though, the object that you are downcasting must be of the correct type. Thus:
Sub s = (Sub)b;
is OK, even if b is declared to be of type Base, but only if it currently contains an object of type Sub. That's not known until runtime, and in your example, is not true. Hence, the runtime exception.
Base b = new Sub(); // OK
Sub s = (Sub)b; // OK
b = new Base(); // OK
s = (Sub)b; // ClassCastException
[ January 22, 2003: Message edited by: Greg Charles ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
What happens when you compile and run the code yourself?


"I'm not back." - Bill Harding, Twister
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
Greg
I dont understand why you say that there is correct type in the cast exprssion Sub s=(Sub) b;
If a class B extends another class A, so that B is the subclass of A, then isnt
A a=new A();
B b = (B) a; //superclass needs a cast to be
//assigned to a subclass
always true,
just like
a=b; //subclass needs no cast to
//be assigned a superclass object
Mathews P Srampikal
Ranch Hand

Joined: Nov 26, 2002
Posts: 211
When ever we use extending a class it always remember to remember that
A SUPER CLASS REFERENCE VARIABLE CAN BE ASSIGNED TO ITS SUB CLASS OBJECT..
Hope you got it...


Thanks,
Mathews
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
Mathews and all,
I know that a superclass can always be assigned its subclass. That is why Im confused why the following gives a runtime exception
class Base {}
class Sub extends Base {}
class Sub2 extends Base {}
public class CEx
{
public static void main(String argv[])
{
Base b=new Base();
Sub s=(Sub) b;
}
}
Can you explain why?
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Think of it this way -- you belong to the class of humans, so does the queen of Britain. A Queen of Britain however, is a sub class of the class of Humans, e.g. the class of Queens.
We can't cast you to be a Queen (of Britain), because you're not a Queen (of Britain). We *can* cast a queen of Britain to a mere mortal human.
Using Java, the notion above translates to:
Human you= new Human();
Queen elisabeth = (Qeen)you;
Translating the class names back to your example, it translates to:
Base b= new Base();
Sub s= (Sub)b;
Get it?
kind regards
ps. no offense intended towards any arbitrary queens neither to other mortals ;-)
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Suppose someone gives you a b and tells you it reference to an object of type Base. Then you know it could be 1) a reference to a real Base object (new Base()) or 2) a reference to a Sub object (new Sub()), which also happens to be a Base , OR 3) a reference to a Sub2 object, which also happens to be a Base.
Now, to assign that reference to a reference of type Sub you must cast the reference to the type Sub. The assigned reference could be a real Sub, but it could also be the Base part of a Sub.
However, there is a risk that it could be the Base part of a Sub2 object or just a Base object on its own.
The cast to (Sub) tells the compiler you are willing to wait until runtime to see if it is really is a Sub.
At runtime the JVM takes a look at the actual object referred to by b and says "Hey!, you told me this is a reference to a Sub object (the cast) but it's really a plain Base object, I object!". So it throws up a ClassCastException.
Sort of....
-Barry
[ January 23, 2003: Message edited by: Barry Gaunt ]

Ask a Meaningful Question and HowToAskQuestionsOnJavaRanch
Getting someone to think and try something out is much more useful than just telling them the answer.
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Ok, suppose you have a Palace which only Queens can live in. Up comes a Human, "I want to to live in that there Palace!". Because you like a easy life and this guy looks a bit like a queen (you know the type) you say OK and stick a "I am a Queen" badge on him.
So this queen goes up to the Palace and the guard says "Who goes there?". "S'me ducky, look at me badge". The guard is suspicious, and does a body search...
A loud exception is raised!
[ January 23, 2003: Message edited by: Barry Gaunt ]
boyet silverio
Ranch Hand

Joined: Aug 28, 2002
Posts: 173
Try the following:
Say you have two animals, a dog and a bear
(represent this statement as follows)
class Animal{}// class Base
class Dog extends Animal{}// class Sub extends Base{}
class Bear extends Animal{}
A dog has its own unique features, so is a bear (represent this as follows)
Dog dog = new Dog();
Bear bear = new Bear();
And an animal could be a dog, or it could be a bear, so the ff is right;
Animal animal = new Dog(); // Base b = new Sub();
Animal animal2 = new Bear();
But a dog could not just be ANY animal (nor a bear be any animal) because it is a dog, so the ff statements are wrong;
Dog d = new Animal(); // Sub s = new Base();
Bear b = new Animal();
------------
Say, in another case, we have a new animal, 'animal3'
Animal animal3 = new Animal();// Base b = new Base();
We can not just convert this 'animal3' into a dog, like the ff:
Dog d = (Dog)animal3;// also not right is
// s = (Sub)b;
or
Bear br = (Bear)animal3;// also wrong
because, that new 'animal' (animal3) is neither a bear (not new Bear()) nor a dog (not new Dog()). It is just a new Animal();
Why can't a dog be a bear (d=br), anyway, they're both animals? Why not? But... well that is probably for a new language with different inheritance rules...
Shashank, this and the previous posts, are ways to remember some of Java's rules on inheritance. Rules that we may not readily understand or agree upon. Nevertheless, these are rules we have to abide to.
You may be treading into the 'why-is-there-such-a-rule' realm (correct me). Regarding the "real why's" of these rules (e.g. rationalizations, why such rule was adapted, etc..), probably the designers could fill in on this. For all we know, even the designers themselves may have seriously argued on why such and such rule was adopted ... and only to end up settling the issues by choosing heads or tails (kidding on this). In the course of using these rules, however, we might find the real reasons or otherwise. And its good to be in such pursuit of knowledge.
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
1) class Y is a subclass of class X. Will this compile? Y myY=new X();
Answer is No
2) class Y is a subclass of class X. Will this compile? X myX=new Y();
Answer is Yes
I can understand these two examples.
class Y is a subclass of class X.
Y myY=new Y();
X myX=new X();
Is myX=myY legal?
Is myY=(Y)myX legal?
Is myX=new Y() legal?
Is myY=(Y)new X() legal?
For example, in the following code
public class InOfComp {
public static void main(String argv[]){
}//End of main
public void mymethod(Component c){
if( c instanceof Button){
Button bc = (Button) c;
bc.setLabel("Hello");
}
else
if (c instanceof Label){
Label lc = (Label) c;
lc.setText("Hello");
}
}//End of mymethod
}
If c can be cast to a label or to a button, because it is an instanceof label or button (by virtue of inheritance I guess), then isnt the same applicable to the example above, so that since class Y is an instanceof class X, it should be able to cast myX to a myY saying myY = (Y) myX;
Why then does myY = (Y) myX; give a runtime error? Isnt the runtime error saying that myY (and therefore class Y) is somehow not the correct type, that is 'is not a myX and therefore not an instancof class X'?? However, by virtue of inheritance and the fact that class Y is a subclass of class X, it does seem that myY should be an instanceof myX, just like c is an instanceof of Label or Button. Where am I going wrong in my understanding?
If my understanding above is not correct, and if you say that Label and Button are both subclasses of component, and that c cannot be cast to either without finding out if it is an instanceof that object,
if (c instanceof Label) Label lc=(Label) c;
then what would make c be an instanceof Label?
What then would then make myX an instance of myY?
Finally, is the (x instanceof y) operator saying that the runtime value of x is equal to y, even though x is a superclass of y?
[ January 25, 2003: Message edited by: Shashank Gokhale ]
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
One of the quotes from Marcus Green's Tutorial is

When assigning one object reference to another the general rule is that you can assign up the inheritance tree but not down. You can think of this as follows. If you assign an instance of Child to Base, Java knows what methods will be in the Child class. However a child may have additional methods to its base class. You can force the issue by using a cast operation.

A cast is needed to assign a superclass to a subclass, according to the quote above, but there is also a possibility of a runtime error if the subclass is not the right type as someone said in earlier posts. So what would it take for an assignment of this type to not cause a runtime or any other error? Please give some code to clarify.
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729

[ January 25, 2003: Message edited by: Barry Gaunt ]
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
Barry,

Human h = new Queen();
Queen q = (Queen)h;
h = new Thug();
q = (Queen)h; //ClassCastException

I understand that a subclass A cannot be casted to another subclass B, even if both A and B are subclasses of the same parent class. So like you have in your example a thug object cannot be cast into a queen object even though a thug and queen both inherit from the human class. Thug and queen are two different types of objects formed from different classes (Thug and Queen)
My question was that if A is a subclass of B, why is
A a=(A) new B();
not legal
and what I gather from your code is that if B is a tyoe A, then the cast is legal, otherwise it cannot be cast. The lines that indicate this are
Human h=new Queen();
Queen q=(Queen) h;
In line 1 you are saying that you want the h object of the Human class to be a reference to a Queen object. And because it is a reference to a queen object, you are able to cast the h object to a Queen object.
In the lines
Human h=new thug();
Queen q=(Queen) h; //ilegal
the object h which now refers to a thug object cannot be cast to a queen object because it is a reference to a thug object.
If you had just said
Queen q=(Queen) new Human();
you would have gotten a runtime error correct?
And if you had said
Human h=new Human();
Queen q=(Queen) h;
you would have still gotten a runtime error, correct, since in neither of these two cases is a human explicitly set to refer to a queen object?
So, in other words, casting a superclass to a subclass doesnt always work, except when the superclass is already a reference to a subclass object.
Am I right in my understanding that if B extends A
A a = B b; is always true buy
B b=(B) a; is not always true?
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729

Put your compiler hat on: Where am I casting a Thug to a Queen? In both cases I am casting a Human reference to a Queen reference.
What if instead of h = new Thug() ( or new Queen()); I had h = makeHuman(); where makeHuman returns a Human? makeHuman() could actually return a Queen, Thug, Human, or any other subclass of Human. Whether I return a Queen or a Thug is decidable only at runtime, so the compiler must allow the casts (Queen)makeHuman() and (Thug)makeHuman(). However, when the assignment actually takes place at runtime h may not actually refer to a Queen, but a Thug. So the cast is always allowed at compile time, but at runtime execution could fail.
At compile time Queen q = (Queen)(new Human()); and Thug t = (Thug)(new Human()); are both allowed, but fail at runtime.
-Barry
[ January 26, 2003: Message edited by: Barry Gaunt ]
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
Barry,

At compile time Queen q = (Queen)(new Human()); and Thug t = (Thug)(new Human()); are both allowed, but fail at runtime.

Okay this is just what I understood, that doing a plain old cast of a superclass (Human) to either a Queen or a Thug would give a runtime error, unless there were preceding statements that caused the Human object to refer to a queen or thug object.
So
Human h=new Queen(); Queen q=(Queen) h;
does compile and not give a runtime error, but
Queen q=(Queen) new Human();
will compile but will also give a runtime error, correct?
Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729
Queen q=(Queen) new Human();
will compile but will also give a runtime error, correct?

That's correct. The best thing is to compile and run the code. That's how I convinced myself. But I will bet I will get it wrong in the SCJP test
-Barry
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
Thanks Barry for your help. And thanks to everyone else too. I knew it worked this way cause I had run a program that did this. I just wasnt sure why a cast would give a runtime error.
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 92
public class Mod
{
public static void main(String argv[])
{}
public static native void amethod();
}
Question in Marcus green's exam 2 with answer:
The above listed code compiles properly, but why if there is a call to amethod, would it give a runtime error?
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Please explain these answers