The sample code is :
public class OverloadingTest {
public static void test(Object obj){
System.out.println("Object called");
}
public static void test(String obj){
System.out.println("String called");
}
public static void main(String[] args){
test(null);
System.out.println("10%2==0 is "+(10%2==0));
test((10%2==0)?null:new Object());
test((10%2==0)?null:null);
}
And the output is :
String called
10%2==0 is true
Object called
String called
The first call to test(null)
invokes the method with String
argument , which is understandable according to The Java Language Specification
.
1) Can anyone explain me on what basis test()
is invoked in preceding calls ?
2) Again when we put , say a if
condition :
if(10%2==0){
test(null);
}
else
{
test(new Object());
}
It always invokes the method with String
argument .
Will the compiler compute the expression (10%2)
while compiling ? I want to know whether expressions are computed at compile time or run time . Thanks.
1) the
test()
method is determined by the type of the parameter at the compilation time :output :
2) The compiler is even smarter, the compiled code is equivalent to just :
you can check the bytecode with
javap -c
:Java uses early binding. The most specific method is chosen at compile time. The most specific method is chosen by number of parameters and type of parameters. Number of parameters is not relevant in this case. This leaves us with the type of parameters.
What type do the parameters have? Both parameters are expressions, using the ternary conditional operator. The question reduces to: What type does the conditional ternary operator return? The type is computed at compile time.
Given are the two expressions:
The rules of type evaluation are listed here. In
B
it is easy, both terms are exactly the same:null
will be returned (whatever type that may be) (JLS: "If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression."). InA
the second term is from a specific class. As this is more specific andnull
can be substituted for an object of classObject
the type of the whole expression isObject
(JLS: "If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.").After the type evaluation of the expressions the method selection is as expected.
The example with
if
you give is different: You call the methods with objects of two different types. The ternary conditional operator always is evaluated to one type at compile time that fits both terms.JLS 15.25:
So the type of
is Object.
Is the same as:
Since type of
o
isObject
(just like the type of(10%2==0)?null:new Object()
)test(Object)
will be always called. The value ofo
doesn't matter.I think your problem is that you are making the wrong assumption, your expressions:
and
Will always call test(null), and that's why they will go through test (Object).
This is what Java Language Specifications say about the problem.
This is test(String) method in your case.
And because of that if you add...
it will show compilation error -The method test(String) is ambiguous for the type OverloadingTest.
Just like JLS says: