Vince
Vince

Reputation: 15128

Integer -> double unboxes, but Double -> int doesn't unbox. Why?

To avoid confusion, I'm looking for the rule/JLS entry.

I'm asking why Integer -> double performs a conversion (unbox & widening), while Double -> int performs no conversion (not even unboxing)

I'm looking for the JLS entry that mentions this Reference -> primitive conversion inconsistency, where unboxing occurs in one situation, but not the other.


This Integer -> double conversion compiles with no error

double d = Integer.valueOf(1);

It implies the following occurs:

  1. Integer is unboxed to int
  2. the int value undergoes a widening primitive conversion from int -> double

Integer is unboxed. The unboxed value is then widened. This gives the same behavior as int -> double


The creates the assumpsion that Double -> int will also unbox, giving the same behavior as double -> int

For the code

int i = Double.valueOf(1);

I would expect the error message

lossy conversion from double to int

Assuming the Double gets unboxed, we should observe the same behavior as double -> int

Instead, we get a typing error

Cannot convert Double to int


What is the explanation behind this behavior?

Why does unboxing occur between Integer -> double, but no unboxing occurs between Double -> int?

Why are these congruent:

But these aren't:

Upvotes: 4

Views: 245

Answers (4)

Vince
Vince

Reputation: 15128

There's a table showing allowed conversions within §5.5:

  • signifies no conversion allowed
  • ω signifies widening primitive conversion
  • ⊗ signifies unboxing conversion

enter image description here

The table shows Integer -> double performs unboxing & widening conversions, but Double -> int does not perform unboxing.

Since unboxing doesn't occur, we get a type error rather than a lossy conversion error.

Upvotes: 0

meriton
meriton

Reputation: 70584

To avoid confusion, I'm looking for the rule/JLS entry.

  • I'm not asking why Double -> int would fail, I'm asking about the way it fails

You're asking for something which doesn't exist.

The Java Language Specification does not generally mandate the wording of compilation errors. In particular, the relevant section of the Java Language Specification merely describes which implicit conversions are permitted in an assignment context, but does not enumerate the combinations of conversions that aren't permitted, let alone which error message should be given in each case (or how to choose the message if several cases apply).

All the specification mandates is that the compiler rejects invalid conversions, how it words the message is up to the compiler implementors, and different compilers actually emit different messages.

For instance, if you ask the Eclipse Compiler for Java to compile

int i = Math.PI;
int j = Double.valueOf(Math.PI);

it says:

Type mismatch: cannot convert from double to int
Type mismatch: cannot convert from Double to int

Upvotes: 0

Double only has two valueOf methods: one for String input and one for double inputs.

So, while you wrote Double.valueOf(1) where that 1 is clearly an int, the method signature is valueOf(double) so (if this were to even run) your int value would get upgraded to a double and then the method runs. As such, your int i = Double.valueOf(1) is really int i = Double.valueOf(1.0) to which the Java compiler goes "a double can't be safely converted to an int, so: no".

Although of course, it doesn't even need to do that: it knows the return value for Double.valueOf is a Double, no matter what you've put in, so it sees code that tries to assign a Double to an int, knows this is impossible, and without caring about anything else, it'll go "RHS is incompatible with LHS, so: no".

Though interestingly, "The[sic] creates the assumpsion[sic] that Double -> int will also unbox" is both wrong (no value unboxing happens) and not entirely wrong (there's type "unboxing"). You're giving Java an assignment with types int = Double, Java sees incompatible types, but also knows that this is a primitive assignment and that Double can unbox to the primitive double. However, as that's still an incompatible assignment, Java nopes out with the original int/Double incompatibility error (so that you know "what's wrong with your code" rather than "what's wrong in whatever code magic the parser applied")

Upvotes: 2

Reilas
Reilas

Reputation: 6266

"... This gives the same behavior as int -> double ..."

That's what the conversion is.  The Integer object is un-boxed to an int.
There is never an Integer to double.

"... Assuming the Double gets unboxed, we should observe the same behavior as double -> int ..."

I don't expect that from Java at all.
And, unfortunately, I don't have the metrics.

I imagine if the value can't un-box and assign in a single operation, the compiler would fail.

Upvotes: 0

Related Questions