Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Why this output? (in Java 5.0)

 
Naseem Khan
Ranch Hand
Posts: 809
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ranchers,

I am not able to figure out why the output of following code is 5 after printing In B

The type of c.getObject() is B. Since we are hiding the int x of A. So B's x must be called.



Thanks in advance

Naseem

[ July 17, 2006: Message edited by: Naseem Khan ]

(topic edited to mention Java 5.0)
[ July 18, 2006: Message edited by: Barry Gaunt ]
 
Jeronimo Sanchez
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The type of the object returned by c.getObject() is not B, but A. Since "c" is a reference to an object of type CovariantTest, the getObject() method which is invoked in the "println" is the one in CovariantTest. That's why you get an object of type A.

If you want to get an object of type B, you should cast the "c" reference as follows:



This will give you the result you expected.
 
wise owen
Ranch Hand
Posts: 2023
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
this thread
 
Jeronimo Sanchez
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry. My explanation is not coorect.
You are completely right!

The object returned by c.getObject() is of type B.

Let me think about it again ;-)
 
Jack Lee
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First I thought the answer is:
In B
6

But I compile and run the code, The answer is
In B
5

The overriden method getObject of B is called (Polymorphism), "In B" is printed and an object of type B is returned.

But object c is type CovariantTest. Therefore, in the place of c.getObject(), the return type is considered as type A. 6 is printed.
 
Naseem Khan
Ranch Hand
Posts: 809
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks everyone. I got this now.

Naseem
 
Shaan Shar
Ranch Hand
Posts: 1249
Java Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Naseem Khan:
Thanks everyone. I got this now.

Naseem



What the hell is JVM working it's totally ambigous from your statements.. Actually When I tried the code and run it.

It is giving output:

In A
5



Now I am totally confused what is the going on in JVM......

 
Shaan Shar
Ranch Hand
Posts: 1249
Java Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One more thing I want to tell you that...

I am using Websphere Studion Application Developer Studio as IDE for JAVA development when I copied this code...

WSAD IDE was showing some error e.g
"The return type is incompatible with CovariantTest.getObject()".

And I thought that program is throwing compile time exception..

And when I tried to run it... it runs smoothly.. and gives the out put like:::----->>>

In A
5



Now what is this please explain this one... it's really ambigous.???
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"The return type is incompatible with CovariantTest.getObject()".


Looks like you have set up your IDE to use Java 1.4 not Java 5.0.

The program compiles and runs using plain vanilla Java 5.0 at the command line so let's forget using IDE's.
 
ram gaurav
Ranch Hand
Posts: 208
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Above i think that you are breaking the overriding policy straight forward.

class SubCovariantTest extends CovariantTest

in this class you override , getObject() , and you just change the return type of the methord , which is just compile time error , there is no question of executing this code.

Thanks
Regards
Gaurav
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jack wrote:
But object c is type CovariantTest. Therefore, in the place of c.getObject(), the return type is considered as type A. 6 is printed.


Unless this is a typo, 6 is not printed - it prints 5.

The returned object from the overridden getObject() is of type B (which is also of type A) and it contains two x values. 5 in the base class A and 6 in the subclass B. Now, as you wrote, the object has to be treated as an object of type A because CovariantTest's getObject() method returns objects of type A. So on dereferencing the x of the return object we get the A.x not the B.x. So 5 is the printed output.
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by ram gaurav:
Above i think that you are breaking the overriding policy straight forward.

class SubCovariantTest extends CovariantTest

in this class you override , getObject() , and you just change the return type of the methord , which is just compile time error , there is no question of executing this code.


No. In Java 5.0 you can do this, but not in Java 1.4 or previous versions.
 
Shaan Shar
Ranch Hand
Posts: 1249
Java Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Barry Gaunt:


No. In Java 5.0 you can do this, but not in Java 1.4 or previous versions.


That means I was correct at my point, that this is a compile time exception But why it was running and giving me wrong output which was not desirable...


 
Rajah Nagur
Ranch Hand
Posts: 239
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Barry Gaunt is right. This works only in JDK 5 (it is a new feature) and above not in previous versions. This page on Sun website gives more clarity on covariant types.

Comming to above question:
The returned object of the method call c.getObject() is of type B. This is determined at runtime. Since B is a subclass of A, the returned object is also of type A.
so c.getObject definitetly instantiates Object B (Which in turn instantiates A as it is a superclass).

But the variable that is printed c.getObject().x is determined at compile time. The return type of c.getObject is A and the x value of A is printed.

I did a javap -c on the CovariantTest.class to verify. Below is the output:



Look at the above line 15. The field A.x is bound at compile time.

So the output is 5.

(Disabled smilies)
[ July 18, 2006: Message edited by: Barry Gaunt ]
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Ankur Sharma:


That means I was correct at my point, that this is a compile time exception But why it was running and giving me wrong output which was not desirable...




There is no compile time exception in Java 5.0. We are discussing Covariant return types, a new version 5.0 feature. Do not confuse the issue by bringing in Java 1.4. Of course you will get a compiler error in Java 1.4. I suggest that you check that your IDE compiler is correctly set up to use Java 5.0, and compile and run the program. If you have problems setting up your IDE then try our IDE forum.
 
Arun Maalik
Ranch Hand
Posts: 216
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sir your program written there is completly wrong. It will create a compile time error that you are not overwriding the method.

Arun
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Arun Maalik:
Sir your program written there is completly wrong. It will create a compile time error that you are not overwriding the method.

Arun


Not in 1.5
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Keith.
For the benefit of those posters who do not know that we are discussing Java 5.0 in this topic, and those who have not bothered to read what was written before they posted, I have modified the topic title to explicitly mention Java 5.0.
 
Anthony Karta
Ranch Hand
Posts: 342
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Could someone explain once more in deep detail?

I use "instanceof" test and it IS an object of type B is returned.

why the return type is considered as type A, and 6 is printed? :roll: sleep
 
Naseem Khan
Ranch Hand
Posts: 809
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I use "instanceof" test and it IS an object of type B is returned.


Even if you check instanceof A or instanceof Object all will give you true value.

Covariant return type is a feature of java 1.5 as Barry edited my subject line.

Naseem
 
Anthony Karta
Ranch Hand
Posts: 342
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I guess we should avoid giving instance variable the same name as superclass??

or we shouldn't use covariant return at all in practice??


so c.getObject definitetly instantiates Object B (Which in turn instantiates A as it is a superclass)


does that mean all superclasses in hierarchy tree will be instantiated during runtime?
 
Ajit Amitav Das
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
first i used this code in eclipse which is using jre1.4 , it gave me compilation error , but in jdk1.5 it complies and runs fine , method binding and data member binding are different , there is no concept of datamember overriding it is just hiding and if u have a datamember in super class and with exact name in subclass then subclass variable hide superclass datamember and u just need same name not even same type also(same name is sufficent for datamember hiding ).Imporant point to note here is "when an instance method is invoked on an object using a refernce it is the class of the current object denoted by the object not the type of reference that determines which method implementation will be executed.But incase of a field(data member) of an object is accesed using a reference, it is the type of reference not the class of the current object denoted by the reference that determines which field will actually will be accessed."
 
saikrishna cinux
Ranch Hand
Posts: 689
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think now this code compiles in jdk1.4 version


but the output is same
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why are you people bringing in Java 1.4? This topic is about a Java 5.0 feature: Covariant returns. We know it does not work in Java 1.4.

Covariant Return Types
[ July 19, 2006: Message edited by: Barry Gaunt ]
 
Pinkal Patel
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
c.getObject().x


Here c refferance of class CovariantTest
And Assigned the Object of SubCovariantTest

Meance Signature of the Method is


Runtime Method called from class SubCovariantTest


Now Return type B is Used fetured of Covariant returntype and convert this object to A.

So O/P is In B followed with 5.

Due to Calling Method of SubCovariantTest and return object is convert to Type A.
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is a very interesting question. Some information can be obtained by looking at the bytecode that is generated.

Consider this example.



After compiling and running javap on Test2, the output is



So I think a reasonable surmise is that in the subclass which overrides a method from a superclass using a refined return type, the return type is determined by the reference type of the caller. That is, if called with a superclass reference, the return type of the method will be determined by the most specific return type that the superclass reference can see.
 
Naseem Khan
Ranch Hand
Posts: 809
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I just made a little twist in my code and I think from the error every thing will be clear why 5 gets printed not 6.



Befor calling x, I assigned the reference of c.getObject() in B. As c.getObject() is returning an instance of B, assignment at line 2 must be valid. But its not.

You will get compilation time error at line 2...


incompatible types
found : A
required: B
B b=c.getObject();


It means what compiler sees c.getObject() as of type A.

One more thing, c.getObject can only be assigned to A or superclass of A not B.

A.x---->>>5

Naseem
 
Anthony Karta
Ranch Hand
Posts: 342
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Naseem Khan:


You will get compilation time error at line 2...
It means what compiler sees c.getObject() as of type A.
Naseem[/QB]


In compile time, "reference type" Always determines which methods/variables can be called, that's why compiler will sees c.getObject() as of type A.

But the issue is, during run-time, c.getObject() is object of type B.
 
nitin pokhriyal
Ranch Hand
Posts: 263
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi naseem,

can you clarify your answer a bit more? at runtime getObject() of subCovarient will be called. am i right? if yes then how can it return object of A?

Regards,
nitin
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by nitin pokhriyal:
hi naseem,

can you clarify your answer a bit more? at runtime getObject() of subCovarient will be called. am i right? if yes then how can it return object of A?

Regards,
nitin


Does this say anything about class B?

 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Following on from Naseem's most recent post, here is another version of the main method based on his example:



To force 6 out of this thing you have to use a cast:


[ July 20, 2006: Message edited by: Barry Gaunt ]
 
nitin pokhriyal
Ranch Hand
Posts: 263
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Barry, i got your point, thanks. Sorry for earlier post but there was a difference what i wanted to ask and what i wrote.. it was totally due to that? sorry once again and thanks for your reply.

Regards,
nitin
 
Akhil Sharma
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just try this simple code:

import static java.lang.System.out;

class A {
int x=5;
public getInt(){
return x;
}
}
class B {
int x=6;
public getInt(){
return x;
}
}
public class Test{
public static void main(String... args){

A a = new A();
B b = new B();
A ab = new B();

out.println(a.x);
out.println(b.x);
out.println(ab.x);
out.println(a.getInt());
out.println(b.getInt());
out.println(ab.getInt());
}

You can easily see that when we print a.x, b.x and ab.x we get the integer values of the instances variables of classes with whose reference is used with the . operator. But when we start using the overridden method the polymorphism comes into picture and the run time class of the ab variable is determined and corresponding getInt() from extended class B is called even though the reference variable used to call the method is of type A. I hope you guys will easily understand this.
Enjoy the code...


}
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Going back to the original code, this is the output of javap on SubCovariantTest.



The JLS talks about this kind of method in relation to generic methods. The method public A getObject() that is included as part of the bytecode of SubCovariantTest is called a bridge method.

Apparently what's happening is that when the runtime type of the object is SubCovariantTest, a call to getObject() still invokes the overridden method by polymorphism, but if the reference type is CovariantTest, then the call is made through the bridge method, and so the return type in that case is A.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic