Wrapper classes - why integer literals fail for Long but work for anything smaller
Asked Answered
A

2

10

Just trying to understand auto-boxing, which I do apart from one thing:

Short s = 250;
Long l = 250;

The assignment to Long l fails. This, I expect, is because you cannot widen then box (i.e. it tries to widen the int value 250 to a long and then box it which it cannot do).

However, the assignment to Short s works. What is going on to make this fine? My assumption was it is still doing boxing and some kind of conversion. But if it's a case of it knowing 250 fits into a short, why does it not know that 250 will fit into a long?

Anabiosis answered 20/1, 2013 at 14:43 Comment(7)
Auto-boxing is evil [Just an opinion]. In my private projects and at the company I work at we treat auto-boxing as errors to avoid any confusions.Chevalier
how does it fail for Long?Derosier
Out of curiosity, what happens to the Short when your literal is 250L? (Offhand I know that specifies a long literal, but I'm not sure if there's a corresponding explicit short literal)Dozer
@archer You get a compiler error complaining about the conversion from int to Long.Tallis
Your question seems to be similar to this oneUnquestioning
@Chevalier - yes. and auto-unboxing is even more evil.Hyohyoid
@David, thanks. I did search but I wanted an answer that showed me why a narrower than int was ok (i.e. Short) but wider (Long) was not. If only primitives were objects like in c#.....Anabiosis
O
15

Normally, you cannot apply multiple (implicit) conversions in assignment (JLS §5.2 Assignment Conversion):

Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of one of the following:

  • an identity conversion (§5.1.1)
  • a widening primitive conversion (§5.1.2)
  • a widening reference conversion (§5.1.5)
  • a boxing conversion (§5.1.7) optionally followed by a widening reference conversion
  • an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

Long l=250; requires two conversions (widening primitive conversion followed by boxing conversion), that's why it doesn't compile.

Long l=250l; compiles because it requires a single boxing conversion.

But narrowing conversion of a constant expression is a special case, that's why Short s=250; compiles:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char or int :

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
  • A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is :
    • Byte and the value of the constant expression is representable in the type byte.
    • Short and the value of the constant expression is representable in the type short.
    • Character and the value of the constant expression is representable in the type char.
Orthman answered 20/1, 2013 at 14:58 Comment(3)
Thanks for the effort you must have took in creating this answer, it is appreciated. So it's a "special case"? I was hoping there was a tangible reason that I didn't understand and could therefore learn rather than something I have to explicitly remember as an exception to the rule kind of thing.Anabiosis
@user1186046: I cannot imagine a tangible reason for this specific case, but perhaps I can make it more clear as follows: the whole concept of narrowing conversion of constant expressions is a special case (because it's the only kind of narrowing conversion that may happen implicitly), therefore it's no surprise that it yields special cases when applied to particular parts of the language.Orthman
Hello, the reason for the case is I'm doing OCJP and the point of the exam is not to test your java knowledge but to test the irrelevant stuff you don't need to know in order for you to buy the examiners' books ;)Anabiosis
H
0

Ideally, no auto narrowing should be allowed.

But since there are no byte/short literals, we can't write

byte b = 0b;

and it seems silly to

byte b = (byte)0;

so auto narrowing of constant integer is allowed so we can write

byte b = 0;

which is carried over to autoboxing case.

For long/Long, since there are long literals, this is less of a problem. Still, it should be allowed, since auto widening of signed integer is always safe.

Hyohyoid answered 20/1, 2013 at 16:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.