2

A simple expression:

Object val = true ? 1l : 0.5;

What type is val? Well, logically, val should be a Long object with value 1. But Java thinks that val is a Double with value 1.0.

It doesn't have to to anything with autoboxing as

Object val = true ? new Long(1) : new Double(0.5);

results with same behavior.

Just to clarify:

Object val = true ? "1" : 0.5;

results in the correct String.

Can anybody explain me why they have defined this like that? For me it seems to be rather really bad designed or actually a bug.

0

5 Answers 5

7

This is described in the Java Language Specification Section 15.25 (relevant parts in bold face):

The type of a conditional expression is determined as follows:

  1. If the second and third operands have the same type [...]

  2. If one of the second and third operands is of type boolean [...]

  3. If one of the second and third operands is of the null type [...]

  4. Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:

    1. If one of the operands is of type byte [...]

    2. If one of the operands is of type T where T is byte, short, or char, [...]

    3. If one of the operands is of type Byte [...]

    4. If one of the operands is of type Short [...]

    5. If one of the operands is of type; Character [...]

    6. Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (§5.1.8) and value set conversion (§5.1.13).

  5. Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7).

The "lub" mentioned in the last paragraph stands for least upper bound and refers to the most specific super type common for T1 and T2.


As for the case with Object val = true ? 1l : 0.5; I agree that it would be more precise if it applied rule 5 (on the boxed values). I guess the rules would become ambiguous (or even more complicated) when taking autoboxing into account. What type would for instance the expression b ? new Byte(0) : 0.5 have?

You can however force it to use rule 5 by doing

Object val = false ? (Number) 1L : .5;
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for pointing it out! So this is done because of a performance issue in the compiler? Performance was higher rated than logical behavior? What is your opinion about that?
Java is statically typed and the expression a ? b : c must have some type, right? So how would you want the type of that expression to be defined?
If both expressions are not convertible as it would be in something like Object val = true ? 1 : new LinkedList(); then it works as expected. So in my opinion it's just done because of a performance issue and only when possible (convertible types) at cost of logical behavior.
4

Because the expression needs to be of a type.

If you do 1l + 0.5d, you end with 1.5d because the compiler changes automatically the types to the one which can allow all possible results.

In your case, the compiler sees ? and assigns the result of the expression the double using the same rule (you can write a long as a double, but not all doubles as longs).

Comments

1

That's not a design flaw:
The compiler has to determine the type of the entire expression true ? 1l : 0.5. It tries using a type where as few conversions as possible are required.
As 0.5 does not fit into a long (without loss of precision), the result of the expression can't be long - therefore, it has to be double and the long is simply converted (no loss of precision).

Note that you can't have an expression conditionally having different types - a tertiary expression has to evaulate to the same type regardless of the condition.

In the second snippet, Object is the only compatible type - the Double gets boxed and the String can be simply assigned.

1 Comment

As 0.5 does not fit into a long, -- uhm, a long does not fit within a double without loss of precision either: 9007199254740993L != (long) (double) 9007199254740993L
1

When you write

Object val = true ? new Long(1) : new Double(0.5);

you need to consider that

(new Long(1) : new Double(0.5))

needs to have a value... The compiler needs to come up with a type that covers both possible values. For your example, it was double.

Comments

0

I cannot provide you with a good reason, but the type of the expression is given by the Java Language Specification: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25

In the JLS all the numeric types are treated as special cases.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.