File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Rules of method overloading broken?? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Rules of method overloading broken??" Watch "Rules of method overloading broken??" New topic
Author

Rules of method overloading broken??

Kenny Johnson
Ranch Hand

Joined: Jan 01, 2007
Posts: 37
NOTE: This discussion and all examples within assume the use of Java 5.0

The Code... what appears to be a override of speak() in Second.



Second is not being overridden, its being overloaded ( or some strange thing like overloading ). But wait you say, the rule for overloads is that the argument list ( the signiture of the method ) must be different, so the compiler knows which one to call. That is what I thought too...

Covariant return types in Java 5. The rule states that "a method in a subclass may return an object whose type is a subclass of the type returned by the method with the same signature in the superclass."

Now lets break down this example as I see it. I see a super class named First, and a sub class named Second. The subclass overrides the speak() method, and because of Java 5's covariant return type rule, changes to return type to String. String is a subclass of Object, so this is legal in Java 5. Now we have a main method, create a reference of type First named obj that points to a instance of Second. Ah now some standard subtype polymorphism about to happen ... the compiler will use dynamic method lookup to see that obj points to a Second and will call the overridden version of speak in Second. OHHH WTF ITS TRYING TO USE THE VERSION IN FIRST??? How could this be I thought to myself.

I went and re-read all about overriding and overloading methods, some polymorphism stuff, rules about covaraint return types.. bla bla bla to make sure I didnt forget some rule. Why oh why was it calling the superclass version, when it should be calling the version in the class that the obj reference points to...

So I then use reflection to find out just what methods the subclass has. I wrote a function that takes in a reference to an object, and then prints out all information about that objects methods. So using it like this


Prints out:

Name: method1
Return Type: java.lang.Object
Parameter Types:
Name: method1
Return Type: java.lang.String
Parameter Types:
Name: hashCode.....then all the other methods in Object like toString etc.

It overloads the method, instead of overriding it. Is that what is going on here? This breaks all the rules of overloading if so.. What is the point of this feature?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Kenny]: Second is not being overridden, its being overloaded

No, nothing in this problem is being overloaded. The method speak() in First is being overridden bey the method speak() in Second. That's it.

[Kenny]: Ah now some standard subtype polymorphism about to happen ... the compiler will use dynamic method lookup to see that obj points to a Second and will call the overridden version of speak in Second. OHHH WTF ITS TRYING TO USE THE VERSION IN FIRST??? How could this be I thought to myself.

The compiler does not use dynamic method lookup, ever. "Dynamic" means the lookup occurs at run time, after the compiler has, errr, compiled. At compile time, the compiler simply assumes that reference obj holds and instance of the declared type of the reference, which is First. You've told the compiler it's a First, and the compiler will continue to assume it's a First. Sure, you've put a Second instance in there, and that's pretty obvious in this case. But the compiler is still just going to assume it's a First, because that's what it's required to do. And because compile-time determination of what type a reference "really" has is often much more complex than it is here, or even impossible. It's much simpler for everyone if the compiler gives consistent behavior that is easy to predict - and the best way to do that, in the opinion of Java's designers, is for the compiler to just assume that a reference holds it's declared type, period. So obj holds a First, and speak() in First returns a String, period - as far as the compiler is concerned. If you want the compiler to treat obj as a Second, you need to declare it as a Second.


"I'm not back." - Bill Harding, Twister
Anton Uwe
Ranch Hand

Joined: Jan 10, 2007
Posts: 122
Mhhh.
So obj holds a First, and speak() in First returns a String, period - as far as the compiler is concerned.

speak() in First returns an Object(which is a String), as far as the compiler is concerned. And an Object cannot be implicitly casted to a String in , there must be an explicit cast like

[ January 13, 2007: Message edited by: Anton Uwe ]
[ January 13, 2007: Message edited by: Anton Uwe ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

I think the thing you may be missing is that while, as Jim says, the compiler can only use the method signatures that appear in First when compiling method calls on a reference variable of type First, if you change that last line to use an Object variable, compile and run the code, you'll see that the overrridden method in class Second is the one that is actually invoked. Try it.


[Jess in Action][AskingGoodQuestions]
Kenny Johnson
Ranch Hand

Joined: Jan 01, 2007
Posts: 37
Oops Im' sorry, I ment to say the JVM will perform dynamic method lookup.Also, if there is no overloading taking place, why does reflection say Second contains both methods?
[ January 13, 2007: Message edited by: Kenny Johnson ]
Anton Uwe
Ranch Hand

Joined: Jan 10, 2007
Posts: 122
Yes. if you replace the last line with (just inserting the cast to String), the compiler is happy and the JVM will call the speak()-method of class Second.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Jim]: So obj holds a First, and speak() in First returns a String,

I misspoke here; the return type is Object.

[Kenny]: Also, if there is no overloading taking place, why does reflection say Second contains both methods?

This is a side effect of how they've implemented covariant returns, redeclaring the superclass method in the subclass with the old return type, and having that methods forward to the the new method. The redeclared method is called a bridge - it's an implementation detail seen by the JVM, not normally accessible from Java source code (other than through reflection). Note that if you try to invoke the First method using an instance of Second, you will still get the subclass method, not the superclass. That's overriding.

[ January 13, 2007: Message edited by: Jim Yingst ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Rules of method overloading broken??