public class OverloadingTest extends Format{
public int add(String s1){
System.out.println("With String");
return 1;
}
public int add(Object a){
System.out.println("With Object");
return 1;
}
public static void main(String[] args) {
OverloadingTest overloadingTest = new OverloadingTest();
overloadingTest.add(null);
}
}
Why is the output of the program With String ?
I have tried reading JLS for 6th Version, but I still could not find the answer.
The only reason I could guess is that the closest match in Inheritance hierarchy is chosen.
So in this case it would take String as Object is its super class.
This answer is available in the question Method Overloading for NULL parameter:
Java will always try to use the most specific applicable version of a method that's available (see JLS §15.12.2).
So, as a result, String is used, because it's the most specific type available. If more than one subtype exists, then you will have to cast null to the appropriate type to designate which function you want to run.
This is spelled out in §15.12.2.5. Choosing the Most Specific Method:
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 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.
In your example, add(Object) can handle anything that add(String) can. This makes the latter more specific. It is therefore the one that gets chosen to handle null.
If more than one member method is both accessible and applicable to a method invocation ... The Java programming language uses the rule that the most specific method is chosen.
See The Java Language Specification
Related
What happens if the actual parameter and formal parameter's data types are different in overloading ?
Class A
{
public void m1(int i)
{
System.out.println("int");
}
public void m1(float f)
{
System.out.println("float");
}
Public static void main(String[] args)
{
A a=new A();
a.m1('a');
a.m1(10l);
}
}
The function corresponding to the arguments types gets called, this is some the basics of OOP not only in java but in all other languages.
The method with the closest matching valid signature gets called. This could well be a direct match (e.g. exactly the same function argument types), or (as in your code) the runtime knows how to automatically convert the char a to an int, so the method with the int param is called.
In overloading method resolution if the matched method with specific argument is not available the compiler won't raise any error immediately,
First it promotes the argument to the next level and check for matched method.
1)If the matched method is available then it will be considered and if it is not available then compiler once again promotes this argument to the next level.
2)This process will be continued until all the possible promotions still if the matched method is not available.Then only we will get compile error.
3)This is called automatic promotion in overloading.
The following are the possible promotions in java
Byte->short/char->int->long->
float->double
I am facing an issue in my program and I made it clear with a small code snippet below. Can anyone explain why this is happening?
class ObjectnullTest {
public void printToOut(String string) {
System.out.println("I am null string");
}
public void printToOut(Object object)
System.out.println("I am null object");
}
class Test {
public static void main(String args[]) {
ObjectnullTest a = new ObjectnullTest();
a.printToOut(null);
}
}
This always prints I am null string .
I want to know the reason so that I can modify the code .
It's because In case of method Overloading
The most specific method is choosen at compile time.
As 'java.lang.String' is a more specific type than 'java.lang.Object'. In your case the method which takes 'String' as a parameter is choosen.
Its clearly documented in JLS:
The second step searches the type determined in the previous step for
member methods. This step uses the name of the method and the types of
the argument expressions to locate methods that are both accessible
and applicable, that is, declarations that can be correctly invoked
on the given arguments.
There may be more than one such method, in
which case the most specific one is chosen. The descriptor (signature
plus return type) of the most specific method is one used at run-time
to perform the method dispatch.
I agree with the existing comment about selection of the most specific method. You can force your null to be treated as an Object reference, eliminating use of the String argument method, by casting it:
a.printToOut((Object)null);
please see section 15.12.2.5 of jls that gives detail regarding how it is chosen
The most specific method is choosen at compile time
LINK TO THE JLS 15.12.2.5
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Method Overloading for NULL parameter
In the code below the output is
String
and if I remove the method with the parameter of type String then the output is
Object
I know how overloading of methods acts when the parameter types don't match exactly but I can not understand how null can be treated as an Object and/or a String parameter.
What is the explanation for this?
class C {
static void m1(Object x) {
System.out.print("Object");
}
static void m1(String x) {
System.out.print("String");
}
public static void main(String[] args) {
m1(null);
}
}
It always uses the most specific method according to the Java specs, section 15.12.2.5.
The intro is reasonably specific about it:
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 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.
Generally speaking, and at least for code readability, it's always best to try to be as explicit as possible. You could cast your null into the type that matches the signature you want to call. But that's definitely a questionable practice. It assumes everyone knows this rule and makes the code more difficult to read.
But it's a good academic question, so I +1 your question.
When multiple overloads match a signature, Java picks the most specific method from among them.
The value of null matches both Object and String, but String is a subclass of Object, so String is picked. If you add another overload with a sibling of String in the class hierarchy, you'd get a compile error.\
// DOES NOT COMPILE
class C {
static void m1(Object x) {
System.out.print("Object");
}
static void m1(String x) {
System.out.print("String");
}
static void m1(Integer x) {
System.out.print("Integer");
}
public static void main(String[] args) {
m1(null);
}
}
Here is a link to a post that discusses your code example at some length.
If you need to force the call of a aprticular overloaded method when passing null as parameter, you have to cast it, like this:
m1((String)null);
By doing this, you make sure you're calling the correct overloaded version of the method.
You have to set the type of null to tell Java what function you want to call.
So you do: m1((Object) null); to call the implementation with the Object parameter and you do m1((String) null); to call the other one.
1. As String is also an object the JVM got confused to call which method at runtime.
2. If you want to specify which method to call at runtime, you can do this by explicit casting
eg:
m1((String)null);
package org.study.algos;
public class Study {
public static void main(String[] args) {
A a = new A();
a.m1(null);
}
}
class A {
public void m1(String s) {
System.out.println("String");
System.out.println(s);
}
public void m1(Object obj) {
System.out.println("Object");
System.out.println(obj);
}
}
Here, the output is
String
null
Why does the JVM resolve the method to one with a String argument?
Thanks in advance
J
It's a fairly elaborate algorithm, detailed in JLS 15.12. But the part that is relevant here is 15.12.2, which says "the most specific one is chosen." Both the Object and String overloads are "accessible and applicable" (the String is applicable because a null literal is a reference of all types), and the String is more specific.
EDIT: Corrected section, per Syntactic.
These methods are "overloaded", not "ambiguous".
According to the Java Language Specification:
When a method is invoked (§15.12), the
number of actual arguments (and any
explicit type arguments) and the
compile-time types of the arguments
are used, at compile time, to
determine the signature of the method
that will be invoked (§15.12.2).
And §15.12.2 says:
There may be more than one such
method, in which case the most
specific one is chosen.
String is more specific than Object, so while null is compatible with both, the method with the String parameter is chosen (there are much more complex rules that apply when the parameter types are part of a class or interface hierarchy).
null value can be set to reference of any type.
All overloaded methods you have are in one inheritance hierarchy Object <- String, the least general one is being choosen.
But if you had two overloaded methods that are not in the same hierarchy, then you'd get compilation error about ambigous methods.
A String is an Object, an Object is not a String, thus the first overload is more specific than the second. See JLS 15.12.2, as Syntactic mentioned.
I asked a similar question. Jon Skeet wrote a big answer.
The link to my question: Which overload will get selected for null in Java?
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 (e.g. 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.
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.
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)