Java - ternary operator weird behaviour

被刻印的时光 ゝ 提交于 2019-11-30 08:05:02

The return type of the ternary conditional operator must be such that both the 2nd and 3rd operands can be assigned to it.

Therefore, in your second case, the return type of the operator is Object (since both d.intValue() and "not whole" must be assignable to it) while in the third case it is Double (since both d.intValue() and d must be assignable to it).

Printing an Object whose runtime type is Integer gives you 5 while printing a Double gives you 5.0.

The type of an expression a ? b : c is always the same as c or the closest common parent of b and c.

System.out.println((d % 1) == 0 ? d.intValue() : "not whole");  // Comparable a parent of Integer and String
System.out.println((d % 1) == 0 ? d.intValue() : d);            // Double is a widened int

BTW d % 1 will only check it is a whole not, not that it's small enough to fit in anint value. A safer check is to see if the value is the same when cast to an int or long

double d = 5.0;
if ((long) d == d)
    System.out.println((long) d);
else
    System.out.println(d);

or you can prevent it widening the long back to a double with

double d = 5.0;
System.out.println((long) d == d ? Long.toString((long) d) : Double.toString(d));

It chooses correctly. Then it wraps it in double. These are 3 key points:

  1. If the second and third operands have the same type, that is the type of the conditional expression. In other words, you can avoid the whole mess by steering clear of mixed-type computation.

  2. If one of the operands is of type T where T is byte , short , or char and the other operand is a constant expression of type int whose value is representable in type T, the type of the conditional expression is T.

  3. Otherwise, binary numeric promotion is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.

In your case the second and third arguments of the ternery operator are types "int" and "Double". Java must convert these values to the same type so they can be returned from the ternary operator. The rules for doing this are given in the Java language specification. https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25

In your case these rules result in the conversion of both parameters to type "double" (the "Double" is unboxed, the int is value-converted).

The fix is to cast the arguments to the ternary operator so that they are of the same type (there may be more brackets in the below than strictly needed, i'm a bit rusty on java operator precedence rules).

System.out.println((d % 1) == 0 ? ((Number)(d.intValue())) : (Number)d); 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!