Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

  • I'm aware of the lossy conversion, as I've mentioned in my question - I'm not asking about data loss between double -> int

  • I'm not asking for someone's "best guess" on why the developers designed it this way

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:

  • Integer -> double
  • int -> double

But these aren't:

  • Double -> int
  • double -> int
like image 527
Vince Avatar asked Oct 19 '25 19:10

Vince


1 Answers

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")

like image 152
Mike 'Pomax' Kamermans Avatar answered Oct 22 '25 09:10

Mike 'Pomax' Kamermans



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!