Given this piece of code
public class Main {
public static void main(String[] args) {
foo(1);
foo("1");
foo(true?1:"1");
foo(false?1:"1");
}
static void foo(int i){System.out.println("int");}
static void foo(String s){System.out.println("String");}
static void foo(Object o){System.out.println("Object");}
}
This is the output I get:
int String Object Object
I can't understand why in the last two cases foo(Object o)
is invoked, instead of foo(int i)
and foo(String s)
.
Isn't the return type for a ternary expression evaluated at runtime?
Edit:
What was confusing me is the assertion that
System.out.println((y>5) ? 21 : "Zebra");
compiles because (OCA Study Guide - Sybex):
The System.out.println() does not care that the statements are completely differnt types, because it can convert both to String
while the point is that println is overloaded to accept Object types as input. Quite misleading, imho.
Isn't the return type for a ternary expression evaluated at runtime?
No, absolutely not. That would be very contrary to the way Java works, where overload resolution etc is always performed at compile-time. What would you expect to happen if you hadn't passed the result to a method, but tried to assign it to a variable? What sort of variable would you have declared?
The expression's type is governed by the rules of JLS 15.25. In both your cases, the third operand is of type String
, leading to this being a reference conditional expression, so table 15.25-E is applied, with a result of lub(Integer,Object)
. The lub
part refers to JLS 4.10.4, which is fairly confusing - the type here isn't exactly the same as just Object
, but in most cases it can be considered that way.
See more on this question at Stackoverflow