5

Code:

public class Foo {

    static void test(String s){
        System.out.println("String called");
    }

    static void test(int s){
        System.out.println("int called");
    }

    public static void main(String[] args) throws Exception {

        test(5>8? 5:8);         // Line 1
        test(5>8? "he":"ha");   // Line 2

        test(5>8? 5:"ha");      // Line 3

        System.out.println(5<8? 5:"ha"); //Line 4
    }
}

When I execute this code I get the following Error at Line 3

Foo.java:24: error: no suitable method found for test(INT#1)
                test(5>8? 5:"ha");              // Line 3
                ^

Using similar type in the ternary operator does not give error. But using different types gives error only to the method call test(5>8? 5:"ha"); but it works for the call System.out.println(5<8? 5:"ha");

When I add another overloaded method static void test(Object s){}, then the //Line 3 compiles.

Can anyone please explain me this scenario?

Anj Jo
  • 137
  • 2
  • 8

3 Answers3

8

Every expression in Java has a type. There are some complicated rules in the Java Language Specification, in the section on the conditional operator that tell us how to find the type of a conditional expression such as 5 > 8 ? 5 : "ha". But in simple terms, you always get the most specific type that both the second and third arguments are members of.

  • For 5 > 8 ? 5 : 8, both 5 and 8 are int, so this whole expression has type int.
  • For 5 > 8 ? "he" : "ha", both "he" and "ha" are String, so this whole expression has type String.
  • For 5 > 8 ? 5 : "ha", the most specific type that fits both 5 and "ha" is Object. So this whole expression has type Object.

Now since you have versions of test that accept int and accept String, the expressions test ( 5 > 8 ? 5 : 8 ) and test ( 5 > 8 ? "he" : "ha" ) both compile.

But if you don't have a version of test that accepts Object, then test ( 5 > 8 ? 5 : "ha" ) can't compile.

This is an over-simplification. The rules are significantly more complicated than I've described, but this is mostly because they consider the various cases involving null operands, auto-boxing and auto-unboxing.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • Now I understand how to determine the return type of a ternary operator. Based on your explanation I wondered whether the method `System.out.println()` has an overloaded method which takes Object as parameter and found there is an `public void println(Object x)` method in PrintStream. If you could add this point in your answer it will be useful for others. – Anj Jo Nov 10 '16 at 08:28
  • I feel that's kind of a different issue. Also, most Java programmers are aware that they can pass any object they like into `System.out.println`. – Dawood ibn Kareem Nov 10 '16 at 08:30
0

You are calling the method before the expression is evaluated. Since the method doesn't have an overload for test(Object o), it doesn't work.

Call the method after resolving the left side expression.

5>8?test(5):test("ha")
SoulRayder
  • 5,072
  • 6
  • 47
  • 93
0

When you are calling the function

test(5>8? 5:8);
Method (in present case) is meant to send the parameter hence whole thing inside the parentheses is considered as parameter and there is no appropriate/suitable method to handle such kind of call (whose parameter should be Object) as you are evaluating int and String in one of the statements . Hence the Ternary operator cannot be implemented there.

Hence you can use code like this

(5 > 8) ? test(param1): test(param2);


or create another test method which accepts Object as parameter and then evaluate things inside that test method. like this

void test(Object o){
    //manipulate things here
}
Tahir Hussain Mir
  • 2,506
  • 2
  • 19
  • 26