• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

question from Dan's exam - ClassCastException

 
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I'm really getting alot out of Dan's mocks (Marcus' are great too!), but I don't quite get ClassCastException runtime exceptions. In the following:
public class BaseTest2
{
public static void main(String [] args)
{
BaseTest2 base = new BaseTest2();
Sub sub = (Sub)base;
}
}
class Sub2 extends BaseTest2
{
}
Compiles fine, but throws a ClassCastException. Now, I understand why the cast is required for compiling, but why is there an exception?
Thanks
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry made a mistake in the code!
public class BaseTest2
{
public static void main(String [] args)
{
BaseTest2 base = new BaseTest2();
Sub2 sub = (Sub2)base;
}
}
class Sub2 extends BaseTest2
{
}
 
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

There are two golden rules for explicit cast:
1. Up-cast is legal
2. Down-cast is not legal.
Say living being is super class. And human being is sub-class. An object of human being (say Barkat) can be casted as living being - that is up-cast.But an object of living being is not necessarily a human being - that is down cast not legal.
In your code you art trying to down cast a super class object (i.e base) to a sub class i.e. sub2, hence you get classcastexception.
Hope this helps.
Barkat.
P.S. Alen if you put your code between
open sq. braket CODE close sq. braket your code open sq. braket /CODE close sq. braket
then code will be nicely indented and in a separate block. Will make life easy.
Thanks. Have a good one.
[ September 12, 2002: Message edited by: Barkat Mardhani ]
[ September 12, 2002: Message edited by: Barkat Mardhani ]
[ September 12, 2002: Message edited by: Barkat Mardhani ]
[ September 12, 2002: Message edited by: Barkat Mardhani ]
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks alot for the response but what I guess I don't get is why does explicit casting exist for objects? Since upcasting is implicit, it doesn't require a cast in the () format as my first example. This compiles just fine:

What situations wouldn't throw a runtime exception, or is it simply there because it is required for primitives and the exception just lets you know that "hey, downcasting is never leagal under any circumstances???"
Thanks again!
 
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It is not that downcasting is always illegal at runtime. In some cases u may use a superclass reference to hold an object of the subclass. In that case, u can get that object back into a subclass reference by using the downcast. I have modified ur program to demonstrate this...

Such a downcast is to instruct the compiler that u know what ur doing, that is u know that ur casting the object reference into a more specialized type. In some cases this may be desirable. For ex suppose Sub2 has a method m2() which is not in BaseTest2. In that case u can't invoke that method using the reference base even though base points to a valid Sub2 type object and has the m2() method. U will have to cast the reference to a Sub2 type reference to make the program compile and invoke m2().
That should be the reason why ClassCastException is a RuntimeException. Only the programmer can predict whether the cast will work or throw an exception !
In ur program, in the second line, ur trying to make a Subclass reference point to a Superclass object. This is not possible since Superclass is higher up in the hierarchy.
Hope this helps
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Thanks alot for the response but what I guess I don't get is why does explicit casting exist for objects? Since upcasting is implicit, it doesn't require a cast in the () format as my first example. This compiles just fine:
public class BaseTest2{
public static void main(String [] args){
BaseTest2 base = new BaseTest2();
Sub2 sub = new Sub2();
base = sub;
}
}
class Sub2 extends BaseTest2{}


Alan: Up-cast is legal but not implicit. The line
in your code:
base = sub ;
is NOT casting anything. All it is saying is that from this point in program variable base will point to same object being pointed by sub (at that this time). The object that was being
pointed to prior to this point, will be discarded
if no other variable is pointing to it.


What situations wouldn't throw a runtime exception, or is it simply there because it is required for primitives and the exception just lets you know that "hey, downcasting is never leagal under any circumstances???"


Alan: Only sitution you will NOT get classcast exception is when cast a derived class object to a super class object (up cast: you are taking an object low in hierarchy and treat it an object high in hierarchy). Come to think of it: you can say that a human being is DEFINITELY a living being. But you CAN NOT say for sure that a living being object is a human being object. So down-cast is never allowed.
Even though up-cast is legal but you have to do explicitly.
In primitives situation is different. You can say that int is long because you are not losing any info so it legal. And it is also automatic i.e. implicit. However, compiler will not automatically convert a long to int because you might lose some info. Therefore you have to explicitly a long to int, you (programer knows better).

originaly posted by Sabarish
It is not that downcasting is always illegal at runtime. In some cases u may use a superclass reference to hold an object of the subclass. In that case, u can get that object back into a subclass reference by using the downcast. I have modified ur program to demonstrate this...
code:
--------------------------------------------------------------------------------
public class BaseTest2 {
public static void main(String [] args) { //Below line is modified to hold subclass object BaseTest2 base = new Sub2(); //The following should now be valid at runtime too Sub2 sub = (Sub2)base; }}
class Sub2 extends BaseTest2 {}
--------------------------------------------------------------------------------
Such a downcast is to instruct the compiler that u know what ur doing, that is u know that ur casting the object reference into a more specialized type. In some cases this may be desirable. For ex suppose Sub2 has a method m2() which is not in BaseTest2. In that case u can't invoke that method using the reference base even though base points to a valid Sub2 type object and has the m2() method. U will have to cast the reference to a Sub2 type reference to make the program compile and invoke m2().


Sabarish: You are talking about polymorphism. Alan's code is not applying polymorhism. You had to change his code to prove your point. Neverthless, even in polymorphism you are not doing real down-cast. Here is what is happening:
1. you have created an object of derived class.
2. you are telling compiler that even that this object is of derived class, I am going to go refer it as an object of super class (i.e. up-cast).
3. after some processing you are going back to compiler and saying that it is enough; from now I want to refer to this oject as derived class object. Compiler says that is fine because it knows that after object belong to derived class.
All of this does not apply to Alan's origial code because he is creating object of base class not derived class.


That should be the reason why ClassCastException is a RuntimeException. Only the programmer can predict whether the cast will work or throw an exception !


I can not follow what is bold.

Hope this helps
Thanks
Barkat
[ September 13, 2002: Message edited by: Barkat Mardhani ]
[ September 13, 2002: Message edited by: Barkat Mardhani ]
[ September 13, 2002: Message edited by: Barkat Mardhani ]
[ September 13, 2002: Message edited by: Barkat Mardhani ]
 
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, let's clarify this with a simple example:

[ September 13, 2002: Message edited by: Ron Newman ]
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ron:
Your example is talking about classcast exception when you cast one derived class to another derived class. Whereas, Alan is talking about casting a super class object to a derived class....
[ September 13, 2002: Message edited by: Barkat Mardhani ]
 
Ranch Hand
Posts: 1055
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Barkat Mardhani:
Hi Ron:
Your example is talking about classcast exception when you cast one derived class to another derived class. Whereas, Alan is talking about casting a super class object to a derived class....


Here you go...
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Good point Anthony. But we are back to square one. Alan is asking why we are getting this classcast exception. Here is copy of his original post:


public class BaseTest2
{
public static void main(String [] args)
{
BaseTest2 base = new BaseTest2();
Sub sub = (Sub)base;
}
}
class Sub2 extends BaseTest2
{
}
Compiles fine, but throws a ClassCastException. Now, I understand why the cast is required for compiling, but why is there an exception?


And I tried to explain why we can not down-cast...
[ September 13, 2002: Message edited by: Barkat Mardhani ]
 
Anthony Villanueva
Ranch Hand
Posts: 1055
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Talk about OOPS programming...
It is important to differentiate between the type of the object reference and the type of the object that object reference refers to at runtime.
Here the runtime type of object referred to by b below is of type Base
Base b = new Base();
Now it is of type Sub.
b = new Sub();
The object reference b can do this because it can refer to objects of type Base or its subclasses, but nothing else. If I did this
b = (Object) new Object();
then a ClassCastException will be thrown. (The cast is mandatory else a compile time error is thrown.) According to the docs, a ClasscastException is


Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance.


In the original example, the object reference base is referring to an object of type TestBase2. An object reference of type Sub can only point to objects of type Sub or its subclasses, hence the ClassCastException was thrown.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Guys,
Thanks a lot for the responses, I'm still struggling though.
Are these two statments equal then ( o is an Object and I is an integer)?



Or am I not understanding something fundamental about casting? To me, casting is taking a Type and forcing something else to fit into it.
In the above I have a variable of the type Object(o). That variable can refer to a variable of the Type Object or one of its subclasses. Now, to me, the purpose of explicit casting is to say, hey I don't have what I want here, I know I'm going to lose some information, but so be it. With primitives, you can say change a float to an integer for example. With implicit casting, no cast () operator is required since there's no loss of bits. But, with Object references it seems that you can't change a Float to an Integer (I know a dog isn't a cat, but I want the compiler to drop the stuff that makes it a cat and now its a dog). Now, since Java is strongly typed, you can't change the type of a variable once it is declared, but wouldn't casting force a variable to accept a type that it isn't?
 
Anthony Villanueva
Ranch Hand
Posts: 1055
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You don't cast objects. You cast object references. If it helps, you can imagine object references to be cups... um ah make that bowls, and objects to be marbles.
A bowl of type A can hold a marble of type A, or any other marble that happens to be a subclass of A. A bowl of type A cannot hold a non-A marble, this is what a ClasscastException means, since you are trying to "drop" a non-A marble onto the A bowl. You can't force a marble A to be a B or C marble anyhow. Um, am I making sense...?
This common confusion about objects and object references reminds me of this little snippet from Beyond the Looking Glass:


"You are sad," the Knight said in an anxious tone: "let me sing you a song to comfort you."
"Is it very long?" Alice asked, for she had heard a good deal of poetry that day.
"It's long," said the Knight, "but it's very, very beautiful. Everybody that hears me sing it -- either it brings the tears into their eyes, or else -- -"

"Or else what?" said Alice, for the Knight had made a sudden pause.
"Or else it doesn't, you know. The name of the song is called 'Haddocks' Eyes.' "
"Oh, that's the name of the song, is it?" Alice said, trying to feel interested.
"No, you don't understand," the Kinght said, looking a little vexed. "That's what the name is called. The name really is 'The Aged Aged Man.'"
"Then I ought to have said, 'That's what the song is called'?" Alice corrected herself.
"No, you oughtn't: that's another thing. The song is called 'Ways and Means': but that's only what it's called, you know!"
"Well, what is the song, then?" said Alice, who was by this time completely bewildered.
"I was coming to that," the Knight said. "The song really is 'A sitting on a Gate': and the tune's my own invention."

 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you very much Anthony!! Fantastic quote!!!
I think it makes sense now!
A rabbit isn't a hat and can never be. The marble example is great. Java is the 1st OO language that I've tried to learn, so it's a bit confusing! Javaranch rocks!
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay, one more question, How can I access the methods in a superclass from a subclass which overides the method. For example:
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
supercl.amethod();
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Barkat,
1) if you mean to call the super() then that won't work since it has to be the first line of a construcor
2) if you mean superclass.amethod(); then that won't work either since amethod is non-static.
Thanks to Roseanne and Anthony, I think I've got it. The code has to be changed to:
superclass subcl1 = new subclass();
superclass super1 = new superclass();
subcl1 = (superclass)super1;
subcl1.amethod();
Then it works fine, since the superclass is already a superclass so it can be cast back from a subclass to a superclass to access the superclasses methods.
Thanks alot everyone!
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't see how that's going to help.
You need to be inside a (non-static) method of the subclass in order to call the superclass's method.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ron,
What I was trying to do was to have the choice to run either the superclass method or the subclass method when the subclass method overrides the subclass method. Declaring it as the superclass but constructing it as a subclass allows both options. I want to have access to the subclass method, but be able to change that to the superclass.
If I call superclass.amethod(); that won't work since the mehtod isn't static. If I call amethod from the subclass, I get the overriden method. Declaring it this way gives access to both methods.
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Could you post an entire program demonstrating how this works -- something I can compile and run?
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sure Ron, here's the complete code. It calls both the superclass amethod and the subclass method:

 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, it calls the subclass's amethod() on the subclass object, and it calls the superclass's amethod() on the superclass object.
It does not demonstrate calling the superclass's amethod() on a subclass object. I still maintain that you can do this only from a non-static method of the subclass.
[ September 16, 2002: Message edited by: Ron Newman ]
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Alan,
Ron is correct. The actual method called will depend on the object's actual type, not the declared type. The naming of the variable does not even come into play. In your code:

you have named your variables in such a way that might lead you to think otherwise but you are still calling the superclass' overridden method through an instance of the superclass (assigned in line 4). It doesn't matter that you name your variable "subcl1", it is still declared as a reference to a superclass, hence the cast is not even necessary. And since on line 5, subcl1 is now referencing a superclass object, it will of course invoke the superclass method.
As far as I know, there is no way you can call the overridden method of the superclass through an instance of a subclass (other than including a "super.method()" in the overriding method).
What you want to do goes against the intent of polymorphism so I am curious to know, what real-world programming situation would require you to do such a thing?
[ September 16, 2002: Message edited by: Junilu Lacar ]
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, that is quite correct. You cannot call the superclass method from a subclass unless it is static.
However, in my example I have both access to the superclass amethod and the subclass and can use a test to create whichever one I want to access.
If I don't want to use the superclass method, then I just don't cast it. If I want to use it then I cast it. If I declare an Object as type superclass and construct it using superclass then I have only access to superclass. If I declare it as a subclass and construct it with subclass then I only have access to the overriden subclass (I can't cast it back to a superclass without a runtime CastClassException). Not what I want. If I declare it as Type subclass then it can be instantiated as a superclass or a subclass.
For example, I'm part of a project and I write a great class with great methods. But Jim comes along and subclasses it and adds some other great methods. Now, I have a situation where if something is true, I want to use my methods, but, if something else is true, I want to use Jim's methods. So, declaring the object as TYPE superclass, and instantiating it as the type subclass then I can do both or neither.
Obviously, this has limited applications, it just came up on one of Dan's mock exam questions...
The only real-world situation (non-scjp study situation!) that this would happen in is through bad planning!!!
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Anthony Villanueva
Ranch Hand
Posts: 1055
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Alan Phillips:
How can I access the methods in a superclass from a subclass which overides the method.


Well, I suppose it can be done, like Junilu suggested, use the super keyword:

But, as Junilu also pointed out, it would seem to be against the spirit of polymorphism to call an overriden method by a subclass instance if your subclass overrode the method in the first place...
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Alan, I just don't see how casting is affecting which method is being called.
If you create a Super object and call its amethod(), you'll get the Super amethod. If you create a Sub object and call its amethod(), you'll get the Sub amethod. This is true regardless of what variables you assign the references to, or how you cast them.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But I want the OPTION to change it later if I want. A subclass can't be changed to a superclass later in order to call the overriden mehtod. Try this:


See, this way I can or cannot use either. It's a really stupid way of doing things I know, but working through it really helped me understand that a superclass can be a subclass or a superclass, a subclass can ONLY be a subclass.
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But you're not calling the superclass method on the same object! You're calling it on a different object.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh yeah! Of course everything would be lost in the conversion. Totally stupid way of doing things. You'd have to create another Object, hold the values and copy them back in. Bad programming, good trick test question!
It does change the runtime types however I've added getClass() to show this

Here is the output:
C:\java>java supersubtest5
Calling the subclass method
sub class
class subclass
Casting and changing to access superclass method
super class
class superclass

So it starts, calls the subclass method with the type of subclass, casts and = a superclass, so it no longer equals the subclass. But, what we're concerned with is the method can be accessed, not the rest of the Object. So it then changes the Runtime type to a superclass allowing access to the superclass methods.
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To add: With Anthony's example the call to super is in the class that extends the other, not possible from an outside class. Unfortunately, I left the original question at work and I'm off to study to write scjp tommorrow. The question was something like:
In the following:
what can replace //here to print "Super Class"
a) subclass_11 subcl = new subclass_11();
subclass_11.super.amethod();
//not an enclosing class error
b) subclass_11 subcl = new subclass();
super.amethod(); //non-static access
c) subclass_11 subcl = new subclass_11();
super.this.amethod();
//not a statement
d) superclass_11 subcl = new subclass_11();
superclass_11 super1 = new superclass_11();
subcl = (superclass_11)super1;
subcl.amethod();
//works

So, here the answer is d, and I don't think that there is another possible way to access the superclass methods from a class that doesn't extend it. If a class extends another, then you can just use super. But, here you can't.
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Allan:
Let us go back to your original question:

prints "super class" for me.


[ September 16, 2002: Message edited by: Barkat Mardhani ]
[ September 16, 2002: Message edited by: Barkat Mardhani ]
[ September 16, 2002: Message edited by: Barkat Mardhani ]
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ah, unfortunately I didn't know what the heck I was talking about then. What I was really after is in the last question. I didn't get the difference between the Run-Time type and the Compliled type. I could just call the class, but what if you want to call both? Since you can't cast from subclass to superclass, if you create a subclass with the type of the superclass you can cast it and use both. If there was an option in the question to call the superclass method directly from a Run-Time and Compile-Time Type superclass, it would work. But, no such option was given!
I would have worded it like:
How is is possible to access both the methods of a superclass and a subclass from an unrelated class when the subclass method overides the superclass method?
[ September 16, 2002: Message edited by: Alan Phillips ]
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Alan Phillips:
working through it really helped me understand that a superclass can be a subclass or a superclass, a subclass can ONLY be a subclass.


Somehow, I just can't help feel that you still don't quite fully understand it. Here are some points for you to ponder:
1. There is a difference between an object reference and the object itself. In the code
SuperClass superRef = new SubClass();
superRef is a reference to an instance of SubClass.
2. Once instantiated, an object's type never changes, no matter how many times you cast or re-cast it. Consider the following code:
SuperClass superRef = new SubClass();
SubClass subRef = (SubClass)superRef;
superRef.aMethod();
subRef.aMethod();
After the second statement, the references superRef and subRef reference the same instance of SubClass. In the first statement, the assignment to a SuperClass reference does not change the object type to SuperClass.
If there is a method aMethod() in SuperClass that is overridden in SubClass, both calls to aMethod (third and fourth statement) will invoke the same method: SubClass.aMethod() because the referenced object is (and always will be) a SubClass.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Junilu,
In your example what I'm trying to not call the same aMethod(). In your example, I want it to print "Super Class" and "Sub Class" from the same variable. I want to be able to call both the superclass and the subclass from the same instance.
This is not possible at the same time of course but possible through casting.
So here, a superclass is a superclass and a subclass and a subclass can only be a subclass. There is no way to call the superclass aMethod() from a subclass subcl = new subclass()! So, I think i'm okay!
The objects compile time type never changes, but the runtime type changes. If you create a variable s1 with a type of superclass and a constructor subclass() the runtime is the subclass. Once you cast it back the runtime type is the superclass. Try it with getClass() to see. The runtime type will determine which methods are called not the compiled type. Because the a TYPE can be a runtime type of itself or its superclass it can have a different runtime type than declared.
Change your example to the following and you get the output I'm looking for:


result:
Sub Class
Super Class
So, using the variable SubRef we can access both superclass and subclass. A variable declared with both compile time types as the superclass could only access the superclass. A variable declared as a subtype can only access the subclasss. This way, we got both.
Now, you could just call superRef.aMehtod(), but in the mock exam question, that was not an option!
If you can think of another way to call both from the same variable, let me know!
[ September 16, 2002: Message edited by: Alan Phillips ]
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There's something fundamental that I think you are not understanding, but I'm not sure I can explain it any better than I've already tried to.
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm, don't think i'm really having a problem, other than explaining that I've got an answer to what I wanted int the first place.
All I wanted to do was create a variable that calls a superclass method and a subclass method from the same Object. This is possible using super. when you extend a class, but not if you instantiate the classes from another class. The way I'm trying to describe is this:
1) create three classes, one extends the other the third is independent
2) create a variable that refers to the compile-time type of the superclass but instantiates it with the subclass type. This will allow this variable to refer to the superclass OR the subclass. Instantiating the variable with soley the subclass or the superclass will only allow access to one of the methods not both.
3) call the method from the variable which is now a compile time type superclass refering to a runtime type subclass
4) cast the Object so it refers to the compile time type superclass then run the method
and voila access to both the subclass methods and the superclass methods!
Another way:
I have a Class Animal and a Class Dog. They both have a method called move() of which Dog overrides.
Now, I'm writing an applet that wants to create a variable that is of the compile type class Dog, but that can use the methods of type Animal (both of the moves). I can't access the method from Animal in type Dog because it's overriden. For some unknown reason I can't just call it from Animal, I need to call it from Dog. So, I cast the type from Dog to animal and voila I get the move() method from DOG
compiletype____runtype___move() of:
Animal_________Dog_______Dog //before cast
Animal_________Animal____Animal //after cast
Can you think of another way Ron to access both overriden methods? Yes, you are effectively replacing the Object, but that's not important, all I want is access to the method, not variables or anything else that would change!
whew! hope that clears it up!
[ September 16, 2002: Message edited by: Alan Phillips ]
[ September 16, 2002: Message edited by: Alan Phillips ]
[ September 16, 2002: Message edited by: Alan Phillips ]
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Originally posted by Alan Phillips:
The objects compile time type never changes, but the runtime type changes. If you create a variable s1 with a type of superclass and a constructor subclass() the runtime is the subclass. Once you cast it back the runtime type is the superclass. Try it with getClass() to see.
This is why Ron and I are getting the feeling that you're still a bit off. The runtime type of an object never changes: once it's instantiated, it will remain the same type no matter what kind of casting you do. Casting merely allows you to reference an object in a more general (upcasting) or specific (downcasting) manner. Casting does not change the type of an object Casting simply allows you to assign the value of one reference variable to another. As an added precaution, the Java Runtime checks if the reference type is compatible with the actual object type; if it isn't a ClassCastException is thrown.
The code:

has some unnecessary lines that I think are misleading you. The casting of superRef2 to SuperClass is not necessary since subRef and superRef2 have the same type: SuperClass. In fact, superRef2 is totally superfluous and I think it is what is leading you astray. The code below has the same effect, without the unnecessary steps. I have changed the variable name to obj to try to make it clearer.

In line 1, the variable obj is declared to be a reference to a SuperClass object. This makes it legal to make it reference any instance of SuperClass as well as any descendant of SuperClass. Line 2 demonstrates this. A cast is not required.
Line 3 demonstrates polymorphism: even though the reference variable obj has a declared type of SuperClass, since the actual runtime type of the object it references is SubClass, SubClass.aMethod will be invoked.
Line 4 reassigns obj. obj is now made to reference another object: a new instance of SuperClass. Thus on line 5, obj.aMethod() invokes SuperClass.aMethod().
I think the terms you are using are also contributing to the misunderstanding.
1. The reference variable obj has a declared type of SuperClass.
2. The runtime type of the actual object that obj references is determined by the argument to new, which in line 2 is SubClass, and in line 4 is SuperClass.
 
Barkat Mardhani
Ranch Hand
Posts: 787
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Junilu:
I know you have intense conversation going on here. I do not want to disturb that. I have side line question prompted by what you said in the bold below:

This is why Ron and I are getting the feeling that you're still a bit off. The runtime type of an object never changes: once it's instantiated, it will remain the same type no matter what kind of casting you do. Casting merely allows you to reference an object in a more general (upcasting) or specific (downcasting) manner. Casting does not change the type of an object Casting simply allows you to assign the value of one reference variable to another. As an added precaution, the Java Runtime checks if the reference type is compatible with the actual object type; if it isn't a ClassCastException is thrown.


I thought you could take a more specific object (say human being) and cast it to be more generic object (say living being) that is up-casting. But you can not do reverse. But you quote is saying you could
:roll:
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Originally posted by Barkat Mardhani:
I thought you could take a more specific object (say human being) and cast it to be more generic object (say living being) that is up-casting. But you can not do reverse. But you quote is saying you could :roll:
Again, casting applies to object references, not the objects themselves. Casting allows you to change the way you "look" at objects. Take this code:

Here's another example, using Animals:

So you see, downcasting is perfectly legal as long as the actual referenced object type is compatible with the reference variable being assigned to.
[ September 17, 2002: Message edited by: Junilu Lacar ]
 
Alan Phillips
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry guys, but try using get class it returns the runtime type and does change after a cast. From the API:
getClass
public final Class getClass()Returns the RUNTIME of an object. That Class object is the object that is locked by static synchronized methods of the represented class.
Returns:
the object of type Class that represents the runtime class of the object.
Try this code:

Here's the output:C:\WINDOWS>cd c:\java
C:\java>java supersubtest5
Calling the subclass method
sub class
class subclass
Casting and changing to access superclass method
super class
class superclass
C:\java>

2. The runtime type of the actual object that obj references is determined by the argument to new, which in line 2 is SubClass, and in line 4 is SuperClass.

Sorry, but this is incorrect. The runtime type is = to the type assigned, not the type instantiated. The type instantiated declares what it CAN be (itself or subclass but not its superclass). Try it with getClass()!The runtime type(as defined by the API can change . If it didn't you couldn't call the methods of the superclass which I've demonstrated you can!
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic