简体   繁体   中英

How does Java pick which overloaded function to call?

This is a purely theoretical question.

Given three simple classes:

class Base {
}

class Sub extends Base {
}    

class SubSub extends Sub {
}

And a function meant to operate on these classes:

public static void doSomething(Base b) {
  System.out.println("BASE CALLED");
}
public static void doSomething(Sub b) {
  System.out.println("SUB CALLED");
}

It seems that the followign code:

SubSub ss = new SubSub();
doSomething(ss);

could legitimately result in printing either BASE CALLED, or SUB CALLED, since SubSub can be casted to both of those. In fact, removing the Sub version of the function causes BASE CALLED to be printed. What actually happens is that "SUB CALLED" is printed. This seems to mean that which function is called doesn't depend on the order the functions are defined in, as the Base version was called first.

Does Java just look at all the different versions of the function and pick the one which requires the smallest traversal up the inheritance stack? Is this standardized? Is it written out in any documentation?

The formal specification can be found in part 15.12.2.5 of the Java Language Specification (JLS) . Thanks to generics this is pretty complicated, so you might want to look at same section of the first edition of the JLS .

It basically says that the compiler tries to find a version of the method where all parameters including the object the method is called upon are most specific. If no such method exists (eg since you have method(Base, Sub) and method(Sub, Base) but not method(Sub, Sub) ), then the compilation fails.

Note that the actual choice of method depends on the dynamic type of the target object for instance methods, but not for the parameters. Your example would still work the same on the instance level.

You should be able to give the compiler a helping hand by casting or redeclaring the type of ss . If the declared type of the variable matches a signature exactly then everything is clear for the compiler and maintenance programmers as well. It doesn't matter if you then assign a more specific type as long as the declared type matches.

As far as I know, Java and C++ make this decision at compilation time (since these are static functions that are not dynamically dispatchable) based on the most specific matching that they can make. If your static type is SubSub and you have an overload that takes SubSub, this is the one that will be invoked. I'm fairly sure it's in both standards.

If you have a reference or pointer to Base, even if it contains a Sub or a SubSub, you will match the version that takes a Base because at compile time, that is the only assurance that the compiler has.

Java binds methods dynamically (in runtime, depending on object instance type, not reference type) but only in context of one method signature. Java binds method signature statically (at compilation time).
In other words , Java makes decision what method (signature) should be called in compile time (statically - reference based - overloading). In runtime Java will take that signature, find proper object in object type hierarchy and execute that method on that dynamically binded object.

Overloading -> what (method signature at compilation time)
Overriding -> from where (object in type hierarchy at runtime)

When you have overloaded static methods then it calls that method that is defined immediately in the class which is invoking the method. If however, no method is defined in the calling class then it will invoke the method inherited from its immediate parent class.

In your case there are two overloaded methods both of which can accept SubSub as parameter. the compiler checks for the most specific match and goes for it. But the most specific match is generally the lowest in the type hierarchy.

EDITED

Removed the conflicting statement. Two methods in classes that are at the same type hierarchy level can't be in ambiguous state for the compiler to choose. This ambiguity is possible only in the case of multiple inheritance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM