Java Language Specification explains that you can narrow int to byte, short or char if the int value is constant and in valid range of the target type:
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.
It's good question, why we cannot widen int to Long, or int to Double? Primitive widening from int to long or int to double is legal.
Seems like the compiler boxes the int value to Integer first? Then of cource you cannot widen Integer to Long or Double, cause IS-A fails. The question is why the compiler doesn't do primitive widening first and then box?
And your question about methods:
Passing values to methods is not same as assigning values to variables (i.e Short s = 10;). The method wrap_byte(Byte b) just don't know what to do with an int or Integer. Narrowing doesn't apply here like it applied to assigning values to variables. For this to work you need to explicitly cast int to byte. Now autoboxing can work.
So for this to work you need:
Notice however that this is legal (because int can be widened to long)
I hope this helps. I'm sure somebody can explain more clear and easier than me
Here's a 'thought experiment' that might help explain some of this behavior...
Consider that before Java 5 there was widening but not boxing. So, if you don't want old, working code to break, and you want to add boxing, what rules would you have to create?
Hi Bert and thanks for taking the time to post a reply. I totally agree that it's better to have us think through an answer to our questions rather than just giving us the answer. We're sure to remember and learn much better that way.
But for this one I really have to say that I just can't figure out why the behaviour in the original question is present.
To prevent old code from breaking you would need:
- widening should always win over boxing when a choice exist (lifted from your book, p.249)
But I can't figure out how this 'rule' creates the conditions that allow an int to be passed to method that expects a Short, but cause a compilation error when you try to declare and initialize a Short using an int.
If Short s = 4; is valid code then I would expect Car().test(4) to be also. But obviously I'm wrong