• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Covariant doubt

 
raja kanak
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

The above code gives output "Derived" when we typecast to String at //1
If (String) removed at //1, it shows error.

method1() is overridden in class Second. When invoking method1() using First reference o, the JVM will call Second version of method1() since o refer to Second object.

If Second version of method1() returns String "Derived", they typecasting is needed at //1 ???

I don't where I missed the logic?

Thanks for any help
 
Srinivasan thoyyeti
Ranch Hand
Posts: 557
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Raja,

Compiler is not as dynamic as you.

Given:
First o = new Second();
String s = (String)o.method1();

here you are invoking method1() on reference of First i.e., o. Then compiler thinks AS o.method1 returns Object, you have to type cast it before assigning to any other class.
 
raja kanak
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So the term covariant return is used in Runtime environment. Am i right?
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you look at the bytecode, it can give you a better idea of what's happening. Consider this example.



Now look at the methods in the bytecode created from Fourth.java.



The methods listed other than the one with return type D have been added to the class definition. This is a form of bridge method that may be used in generics.

Depending on the reference type, the appropriate bridge method is invoked.

This means that if a reference of type A refers to an object of type D, and invokes the method method1(), then the first method invoked will be the one with return type A. Then the overridden method in D will be called. But it will be called from the bridge method. However, the type of object returned by the method will be A.

You can see this by what is printed out in the second set of print statements.

You know that if you access a static member of a class using an instance of the class, then the class type will be substituted by the compiler in the method call.

So first.method1().x will refer to the static variable x in the class definition which is the type of first.method1().

So 1 is printed.



If you look at the full bytecode for Fourth, you can see what's happening.


[ March 02, 2007: Message edited by: Keith Lynn ]
 
raja kanak
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wonderful explanation Keith.

The methods listed other than the one with return type D have been added to the class definition. This is a form of bridge method that may be used in generics.

Depending on the reference type, the appropriate bridge method is invoked.

This means that if a reference of type A refers to an object of type D, and invokes the method method1(), then the first method invoked will be the one with return type A. Then the overridden method in D will be called. But it will be called from the bridge method. However, the type of object returned by the method will be A.

I don't know anything about bride method. Can you please explain or give me any link to learn?

You can see this by what is printed out in the second set of print statements.

I can't follow the second set of print statement
I guess the answer hidden behind bridge method!!


You know that if you access a static member of a class using an instance of the class, then the class type will be substituted by the compiler in the method call.

So first.method1().x will refer to the static variable x in the class definition which is the type of first.method1().

So 1 is printed.

This point is clear.
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's not much discussion about it in the Java Language Specification, but here is one paragraph where they talk about bridge methods.

This is from the Java Language Specification 15.12.4.

As an example of such a situation, consider the declarations:
class C<T> { abstract T id(T x); }
class D extends C<String> { String id(String x) { return x; } }
Now, given an invocation
C c = new D();
c.id(new Object()); // fails with a ClassCastException
The erasure of the actual method being invoked, D.id(), differs in its signature from
that of the compile-time method declaration, C.id(). The former takes an argument of
type String while the latter takes an argument of type Object. The invocation fails with a
ClassCastException before the body of the method is executed.
Such situations can only arise if the program gives rise to an unchecked warning
(�5.1.9).
Implementations can enforce these semantics by creating bridge methods. In the
above example, the following bridge method would be created in class D:
Object id(Object x) { return id((String) x); }
This is the method that would actually be invoked by the Java virtual machine in
response to the call c.id(new Object()) shown above, and it will execute the cast and
fail, as required
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The reference variable o is of type First. First has only a method1() that returns an Object. You cannot assign the returned Object to a String without a cast. It's as simple as that. I think that also is the meaning of what Srinivasan was trying to convey.
 
raja kanak
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for all your efforts friends.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic