By Lemonov


2018-06-13 14:04:58 8 Comments

I was playing with ternary operator and noticed something odd. I have code below:

class Main {

  static void foo(int a){
    System.out.println("int");
  }

  static void foo(String a){
    System.out.println("String");
  }

  static void foo(Object a){
    System.out.println("object");
  }

  public static void main(String[] args) {
    foo(2==3 ? 0xF00:"bar");
    System.out.println((2==3 ? 0xF00:"bar").getClass().getName());
  }
}

Which results in

object

java.lang.String

First line of result shows that this instruction passed to foo method with object parameter.

Second line that the instruction itself results in String.

Question:

  1. Why if result is String compiler decides to go with Object?

  2. Is this because of the type ambiguity?

  3. If yes then why getting class name returned java.lang.String?

3 comments

@Shubham Kadlag 2018-06-13 14:38:22

You can skip to Summary if not interested in reading.

Refer the JavaDoc here: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25

Under 15.25.3. Reference Conditional Expressions It says:

The type of the conditional expression is the result of applying capture conversion

For capture conversion : https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.10

Summary:

For type determination, capture conversion is used, wherein for your example int is first boxed to Integer and then the closest common super class of Integer and String is fetched, which is Object class. So the type for the Conditional Expression is Object and so the method with Object as parameter is called.

Now for second part, the Conditional operator is evaluated first, then it is unboxed and then .getClass() is evaluated. So it prints java.lang.String.

This is also documented here: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25

Under 15.25. Conditional Operator ? :

At run time, the first operand expression of the conditional expression is evaluated first. If necessary, unboxing conversion is performed on the result.

@Leo Aso 2018-06-13 14:25:47

In Java, you have compile time type information and you have run time type information. Compile time type information is what the compiler can deduce about the type of a value or expression just by looking at it, but without executing it. When the compiler sees the expression

2 == 3 ? 0xF00 : "bar"

It does not know whether 2 == 3 will be true or false, because it does not execute code. So all it knows is that the result can be an Integer, or a String. So when the time comes to pick which foo method to call, it picks the one that accepts Object, since that is the only one that it knows will work in both scenarios.

However, when the code is actually running, 2 == 3 will be false, and the result will be a String, whose getClass() method will return String.class. And that is what you need to note: getClass() does not return the type that the variable had at compile time, but it returns the actual type of the object that the variable holds at run time. i.e.

Object o = "Hello!";
System.out.println(o.getClass());

will print java.lang.String, because even though to the compiler it is an Object, at run time it is actually a String.

@JohnSnowDoesNotKnowNothing 2018-06-13 14:15:18

At compile stage, the compiler noticed that the result of 2 == 3 ? 0xF00 : "bar" could be int or String. To be compatible with both, it decide to call foo(Object a).

At runtime, the result of 2 == 3 ? 0xF00 : "bar" is String bar.

@Jonathan Rosenne 2018-06-13 14:20:10

The int is first boxed.

Related Questions

Sponsored Content

22 Answered Questions

6 Answered Questions

[SOLVED] Java - Method executed prior to Default Constructor

  • 2015-09-21 06:27:44
  • Rohit Nigam
  • 3278 View
  • 24 Score
  • 6 Answer
  • Tags:   java constructor

36 Answered Questions

[SOLVED] Differences between HashMap and Hashtable?

31 Answered Questions

[SOLVED] Difference between StringBuilder and StringBuffer

11 Answered Questions

26 Answered Questions

6 Answered Questions

[SOLVED] Ternary operation in CoffeeScript

4 Answered Questions

[SOLVED] Why is -1 zero fill right shift 1=2147483647 for integers in Java?

  • 2013-12-07 09:28:18
  • Praveen Vinny
  • 707 View
  • 11 Score
  • 4 Answer
  • Tags:   java bit-shift

5 Answered Questions

[SOLVED] java static initialization with inheritance

Sponsored Content