File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Covariant problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Covariant problem" Watch "Covariant problem" New topic
Author

Covariant problem

Henry Zhi Lin
Ranch Hand

Joined: Nov 04, 2008
Posts: 69
What is the result of compiling and runing the following program?

class A {
int x = 5;
}

class B extends A { int x = 6 }

public class CovariantTest {
public A getObject() { return new A(); }
public static void main(String[] args) {
CovariantTest c1 = new SubCovariabntTest();
System.out.println(c1.getObject.x);
}
}

class SubCovariantTest extends CovariantTest {
public B getObject() {
return new B();
}
}

[A] Does not compile [B] Throw ClassCastException [C] prints 5 [D] prints 6

My answer is D. But the answer is actually C. Can some one give idea why?

As Covariant class it should use SubCovariantTest's getObject, if so then it should return Type B not A, then it should print 6 not 5 here?


SCJP 5.0
Ravikanth kolli
Ranch Hand

Joined: Feb 10, 2008
Posts: 179

hi Henry Zhi Lin ,
welcome to javaranch.

Can you mention the source for the program. As mentioned in this


-kolli
Jennifer Gamble
Greenhorn

Joined: Sep 12, 2008
Posts: 9
Hi Henry,

Actually, you have a compiler error in your code. You are overriding method getObject(), however you are using two different return type Objects. You have public A getObject(){} and public B getObject(){}. This is an illegal override. If you were to legally override the method, then the method called would be the method of the reference type object, CovarientTest.getObject().

Hope this helps,

Jennifer


Love and Peace
Steven Landers
Ranch Hand

Joined: Nov 02, 2008
Posts: 30
This is actually legal code -

Prior to Java 5, we were not able to change the return type for any return type of an overriding method. As of Java 5, an overriding method may return a subclass of the return type of the overridden method. This works because the retuned object is "reduced" to the type of its supertype - in this case, type A. So SubCovariantTest's getObject is running. In this example, the c1.getObject() is returning an object of type B, except it is returned in the type of it's supertype - type A.


In effect:
////////////////////////////////
Calling:
A myResultingA = c1.getObject() (this returns type B via a reference of type A)

is similar to:
List<Integer> myList = new ArrayList<Integer>();
////////////////////////////////////

Try casting the result of c1.getObject() - it should print 6. It also helped me to put a print statement in each method.

class A {
int x = 5;
}

class B extends A { int x = 6 }

public class CovariantTest {
public A getObject() { return new A(); }
public static void main(String[] args) {
CovariantTest c1 = new SubCovariabntTest();
System.out.println(((B)c1.getObject()).x);
}
}

class SubCovariantTest extends CovariantTest {
public B getObject() {
System.out.println("SubCovariantTest is running");
return new B();
}
}

In most of the exam questions I've run across, this isn't an issue, as we're just testing to see which method ran - and not what the effect of the return type really is.

Good luck! I have my test tomorrow - yikes.
[ November 04, 2008: Message edited by: Steven Landers ]
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9280
    
  17

Steven gave a good explanation here. The original code works in this manner


[ November 04, 2008: Message edited by: Ankit Garg ]

SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Arron Ferguson
Greenhorn

Joined: Feb 01, 2005
Posts: 28
If I may chime in (and put my head on the chopping block at the same time ), it appears to me that the new covariant feature of Java 5 is allowing the sub-type to be different, however, this doesn't appear (to me anyways) to be a covariant/contravariant/invariant issue pertaining to the OP's question. This is more of polymorphic behavioral issue - specifically what is considered a compile-time decision and what is considered a run-time decision. The above code reworded, and with an addition:




Two things above that are of interest:
1) Whether using the new invariant behavior or not, the output is the same. That is, with or without the invariant feature invoked, the output doesn't change.
2) Within the context of polymorphic behavior, an instance variable is decided at compile time whereas the instance method is decided at runtime (i.e., 5 is printed from the A class, but "Ima 'B'" is printed from the B class.

I don't know if the test gets this ugly, but this is something nice to know - at least if you're dealing with large/complex class hierarchies.

On a side note, if you are looking for an interesting read on invariants, this is a good read:
http://barrkel.blogspot.com/2006/07/covariance-and-contravariance-in-net.html

I found the descriptions quite informative.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 13872
    
  10

Henry, welcome to JavaRanch.

We have a rule here: when you copy a question from a book, mock exam or other source, you are required to quote your sources. So, please tell us where you copied this question from.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Henry Zhi Lin
Ranch Hand

Joined: Nov 04, 2008
Posts: 69
Originally posted by Ravikanth kolli:
hi Henry Zhi Lin ,
welcome to javaranch.

Can you mention the source for the program. As mentioned in this


This question from WhizLabs. I do appologies, there are lots of miss typing.

The following should be a compiled code.

Henry Zhi Lin
Ranch Hand

Joined: Nov 04, 2008
Posts: 69
Originally posted by Steven Landers:
This is actually legal code -

Prior to Java 5, we were not able to change the return type for any return type of an overriding method. As of Java 5, an overriding method may return a subclass of the return type of the overridden method. This works because the retuned object is "reduced" to the type of its supertype - in this case, type A. So SubCovariantTest's getObject is running. In this example, the c1.getObject() is returning an object of type B, except it is returned in the type of it's supertype - type A.


In effect:
////////////////////////////////
Calling:
A myResultingA = c1.getObject() (this returns type B via a reference of type A)

is similar to:
List<Integer> myList = new ArrayList<Integer>();
////////////////////////////////////

Try casting the result of c1.getObject() - it should print 6. It also helped me to put a print statement in each method.

class A {
int x = 5;
}

class B extends A { int x = 6 }

public class CovariantTest {
public A getObject() { return new A(); }
public static void main(String[] args) {
CovariantTest c1 = new SubCovariabntTest();
System.out.println(((B)c1.getObject()).x);
}
}

class SubCovariantTest extends CovariantTest {
public B getObject() {
System.out.println("SubCovariantTest is running");
return new B();
}
}

In most of the exam questions I've run across, this isn't an issue, as we're just testing to see which method ran - and not what the effect of the return type really is.

Good luck! I have my test tomorrow - yikes.

[ November 04, 2008: Message edited by: Steven Landers ]



Thanks for your answer, now I do understand it a bit of clear.
Henry Zhi Lin
Ranch Hand

Joined: Nov 04, 2008
Posts: 69
Hi guys,

Thanks for all your answers. Now I do have a clue why this convariant class behaves like this.

Thanks for all your help.
subhasish nag
Ranch Hand

Joined: Apr 25, 2008
Posts: 101
Can anybody explaim why there is refence type is selected incovariant overrinding.


Thanks,<br />Subhasish
Henry Zhi Lin
Ranch Hand

Joined: Nov 04, 2008
Posts: 69
I guess this is downto the following statement

Object type (not the reference variable's type), determines which overridden
method is used at runtime.

Reference variable type (not the Object type), determines which instance variable is used at compile time.
Tuna Töre
Ranch Hand

Joined: Aug 17, 2008
Posts: 219

YES


blog: http://tunatore.wordpress.com
SCJP 6.0 + SCWCD 1.5
Rekha Srinath
Ranch Hand

Joined: Sep 13, 2008
Posts: 178
Its understood that the object type determines which overridden method should be invoked at runtime.

then, why does the following code runs the way it runs? (From one of the replies above from Ankit in this mail thread)



I am specifically not clear on this...Why does not B b = c1.getObject(); compile without a (B) cast?

I thought for this function call, SubCovariantTest's getObject() would be called and the resulting B object could be assigned to b reference variable...But seems that is not the case... Anyone please clarify this doubt of mine.
Ganeshkumar cheekati
Ranch Hand

Joined: Oct 13, 2008
Posts: 362
i am confused.....

can anyone give clarification?


SCJP5 and SCWCD1.5
Think Twice Act Wise...
Arron Ferguson
Greenhorn

Joined: Feb 01, 2005
Posts: 28
I guess this is downto the following statement

Object type (not the reference variable's type), determines which overridden
method is used at runtime.

Reference variable type (not the Object type), determines which instance variable is used at compile time.


Yes, correct. Which really has nothing to do with covariance - at least not with the code example you posted since you can duplicate the same behavior without using the covariant feature of Java 5.
Rekha Srinath
Ranch Hand

Joined: Sep 13, 2008
Posts: 178
Arron,

Yes, you are right. Those statements in your quotes can be explained without bringing in covariance.

But, I am unable to understand why B b = c1.getObject(); does not compile without a (B) cast
Jennifer Gamble
Greenhorn

Joined: Sep 12, 2008
Posts: 9
My apologies. I compiled the code above on the older java 1.4 compiler. I had forgotten that overriding methods are allowed to return subtype objects as of java 5.
Arron Ferguson
Greenhorn

Joined: Feb 01, 2005
Posts: 28
Arron,

Yes, you are right. Those statements in your quotes can be explained without bringing in covariance.

But, I am unable to understand why B b = c1.getObject(); does not compile without a (B) cast


Because it's a downcast. The c1 variable is of type CovariantTest. CovariantTest's getObject method returns an 'A' type object. You're telling it to put (force really) an 'A' instance into a 'B' reference. You are thus going down the inheritance hierarchy and therefore you are performing a downcast.

The Java compiler wants you to be good and sure you are aware of this because it could cause problems. For example, you could start off with a Cat object (whose superclass is Animal), and then use an animal reference to the Cat object (upcast). Then you later (and erroneously) take the animal reference and downcast it to a Dog (whose superclass is also Animal). As we know, you can never turn a dog into a cat (or vice versa - very unnatural!). The Java VM would throw a ClassCastException (possibly) causing problems in your program state.

A good read is found here:
http://javaforyou.wordpress.com/2008/06/22/casting-reference-variables-downcasting-upcasting/
Ganeshkumar cheekati
Ranch Hand

Joined: Oct 13, 2008
Posts: 362
Hi arron.

c1.getObject();
it will call the getObject method in the sub class because of overriding and it returns B object.
Arron Ferguson
Greenhorn

Joined: Feb 01, 2005
Posts: 28
Hi arron.

c1.getObject();
it will call the getObject method in the sub class because of overriding and it returns B object.


Uh no, no it does not, it returns 5. Run the code, read the blog link article and see for yourself, the downcast rules are clear.
subhasish nag
Ranch Hand

Joined: Apr 25, 2008
Posts: 101
Uh no, no it does not, it returns 5.

Yes.that is the problem why c1.getObject() is not returning B instead of A.
Here as it overriding so object type(CovariantTest c1 = new SubCovariabntTest() to be choosed as runtime ,as a result
public B getObject(){} to be invoked (which return B not A).Can anybody please explain this.
But when I change the code
CovariantTest c1 = new SubCovariantTest();
B b = (B)(c1.getObject());
System.out.println(b.x);
It will return 6.
So the question is actually
Is the covariant overriding has some more special characteristics??
Ganeshkumar cheekati
Ranch Hand

Joined: Oct 13, 2008
Posts: 362
hi arron..
i read it.
i think that is the situation in which method is only available in sub class but not in super class.
we can't call that method using super class ref so we have to do downcasting...

by executing below code we know which method is executing (super or sub)

class A {
int x = 5;
}

class B extends A
{
int x = 6; }

public class CovariantTest {
public A getObject() {
System.out.println("super method:");return new A(); }
public static void main(String[] args) {
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}

class SubCovariantTest extends CovariantTest {
public B getObject() {
System.out.println("sub method:");
return new B();
}
}
[ November 05, 2008: Message edited by: Ganeshkumar cheekati ]
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9280
    
  17

what the heck is happening here??? Everyone should go and read a book instead of being confused like this...
Ganeshkumar cheekati
Ranch Hand

Joined: Oct 13, 2008
Posts: 362
thats good thing ankit.

what is your explanation regarding this topic?
Rekha Srinath
Ranch Hand

Joined: Sep 13, 2008
Posts: 178
Arron,

Thanks for the explanation.I think I got it...

c1.getObject(); -- This line of code, at runtime, can invoke either the
Case 1: getObject() of CovariantTest or
Case 2: SubCovariantTest,
depending on the type of object that c1 points to. This is a purely a runtime decision and we cannot control it during compilation.

Case 1: If the getObject() of CovariantTest is invoked, then an object A is returned. So, you do the downcast using the code (B)c1.getObject(), thus safely assigning a B type object to a B type reference.

Case 2: If the getObject() of SubCovariantTest is invoked, then an object B is returned, which can again be safely assigned to the B type reference. (The cast (B) is meaningless in this case).

So, to provide this safety measure, the compiler ensures that you downcast to avoid ClassCastException, because at runtime, the reference invoking getObject() can be either CovariantTest or SubCovariantTest.

In case of overriding not involving any covariant return types, there is no issue at all, because the return types of the parent and subclass methods are going to be the same.

Correct me if I am wrong in my understanding.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Covariant problem
 
Similar Threads
Covariant Return Types
Overriding question
overriding with variables - whizlabs
Query on covariant return --- SCJP 5.0
Problem in polymorphism