| Java FAQ | ||
| JSP FAQ | ||
| Servlet FAQ | ||
XyzWs Java FAQ:
What is a most-specific method?
Printer-friendly version |
Mail this to a friend
|
Advertisement
|
What is a most-specific method?Resolving a method name at compile time is more complicated than resolving a field name because of the possibility of method overloading. Invoking a method at run time is also more complicated than accessing a field because of the possibility of instance method overriding. Suppose that more than one version of an overloaded method applies to a particular call. When evaluating a method invocation expression that invokes an overloaded method, the compiler must determine which of the overloaded methods is the most specific (referred to as the "most specific method"). The same rules apply to constructors, however, which means the most specific method actually may be the most specific constructor.
Determining the method that will be invoked by a method invocation expression involves several steps: Step1. Determine Class or Interface to Search The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to check for definitions of methods of that name. There are several cases to consider, depending on the form that precedes the left parenthesis, as follows:
Step 2. Determine Method Signature The second step searches the class or interface determined in the previous step for method declarations. This step uses the name of the method and the types of the argument expressions to locate method declarations that are both applicable and accessible, that is, declarations that can be correctly invoked on the given arguments. A method declaration is applicable to a method invocation if and only if both of the following are true:
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen. The informal intuition is that one method declaration is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error. The precise definition of the most specific property is as follows. Let m be a name and suppose that there are two declarations of methods named m, each having n parameters. Suppose that one declaration appears within a class or interface T and that the types of the parameters are T1, . . . , Tn; suppose moreover that the other declaration appears within a class or interface U and that the types of the parameters are U1, . . . , Un . Then the method m declared in T is more specific than the method m declared in U if and only if both of the following are true:
A method is said to be maximally specific for a method invocation if it is applicable and accessible and there is no other applicable and accessible method that is more specific. If there is exactly one maximally specific method, then it is in fact the most specific method; it is necessarily more specific than any other method that is applicable and accessible. It is possible that no method is the most specific, because there are two or more maximally specific method declarations. It's not possible to identify a most-specific method from among the applicable methods. In this case, we say that the method invocation is ambiguous, and a compile-time error occurs. More about more maximally specific methods: The types of the actual arguments in the method invocation or class instance creation expression are no part of overloaded method matching. This is where the conceptual difficulty arises; overloading method matching begins with a list of applicable methods. Instead of using the types of the actual arguments, overloaded method matching in the Java programming language compares formal parameter types in the list of applicable methods. It is possible that no method is the most specific, because there are two or more maximally specific methods. In this case:
Example IIn the following example:
public class Test {
void print(Object o) {
System.out.println("void print(Object o)");
}
void print(String s) {
System.out.println("void print(String s)");
}
public static void main(String[] args) {
new Test().print(null);
}
}
The print() method is overloaded to take either Object or String types
as an argument. We call the print method with a "null" literal as the
parameter in the main function. Which print method will be invoked with
such call? In this situation, Java invokes the "most-specific" method, as
detailed in section 15.12.2.2 of the Java Language Specification. In general,
one method is considered more specific than another if its argument types are
subtypes of the other method's respective argument types.
Any kinds of Java object reference can be null, the special null reference can be passed as the argument for both Object and String argument methods (a null reference can be converted to any type of object). Therefore, calling print(null) could potentially invoke either print(String s) or print(Object o). The type of the null argument is only used to determine the applicable methods. In general, a method declaration is "more specific" than another if its respective arguments could be converted (via method invocation conversion) to those of the other method. Recall that any classes in Java are direct or indirect subclasses of Object. So String is a subtype of Object, the method overloaded to accept a String is more specific than the method overloaded to accept an Object. A String can be converted (upcast) to Object, but an Object cannot be converted (downcast or upcast) to String, so the method taking the String argument is more specific. Therefore, print(String s) will be invoked by the call print(null). Example IILet's look another example:
public class Test {
void print(StringBuffer sb) {
System.out.println("void print(StringBuffer sb)");
}
void print(String s) {
System.out.println("void print(String s)");
}
public static void main(String[] args) {
new Test().print(null);
}
}
This example results in a compiler error, as expected. Again, a null reference can be converted to any type of object. Therefore, calling print(null) could potentially invoke either print(String s) or print(StringBuffer sb). The both of String and StringBuffer are a subtype of Object, a String cannot be converted to a StringBuffer, nor can a StringBuffer can be converted to a String (since neither extends the other). It's not possible to identify a most-specific method from among the applicable methods, because there are two maximally specific method declarations. So the method invocation is ambiguous, and a compile-time error occurs. |