Reputation: 15128
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:
Integer
is unboxed to int
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
Upvotes: 4
Views: 245
Reputation: 15128
There's a table showing allowed conversions within §5.5:
- signifies no conversion allowed
- ω signifies widening primitive conversion
- ⊗ signifies unboxing conversion
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
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
Reputation: 53735
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
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 asdouble -> 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