Why Short.valueOf (n) requires listing
As per this answer, int constant is implicitly convertible to short type.
But in my unit test, I want to test the getValue () function that returns a Short .
assertEquals(obj.getValue(), 42);
Obviously this doesn't work, so I am trying to use Short.valueOf
assertEquals(obj.getValue(), Short.valueOf(42));
However, this still complains - despite the above implicit conversion - so I have to use a literal.
assertEquals(obj.getValue(), Short.valueOf((short)42));
Short.valueOf ((short) 5) seems a little messy! Is there a cleaner way? (the new short ("42") is equally awful!)
This is because converting a number from int
to short
may fail (overflow) as it is a narrowing of the primitive conversion . In theory, the compiler could recognize that the argument is a constant expression, and it can determine if the conversion is valid at compile time. But this is not the case.
A cleaner way:
Short s = 42; //autoboxing is done here
assertEquals(obj.getValue(), s );
The reason for the above is that the rules for assigning variables are different. This is where the compiler actually checks if the constant expression can be converted to short
without overflow.
Additionally, if the expression is a constant expression (Β§ 15.28) of type byte, short, char, or int:
A narrowing primitive conversion can be used if the type of the variable is byte, short, or char, and the value of the constant expression is represented in the type of the variable.
A narrowing of the primitive conversion followed by the boxing conversion can be used if the type of the variable is:
Byte and constant expression value can be represented in byte type.
In short, the value of the constant expression is represented in type short.
The sign and value of a constant expression can be represented as char.
This is in bold.
The other answers explain why you have this problem. A cleaner option for your code might be:
assertEquals(obj.getValue().intValue(), 42);
Although biziclop indicates , this will throw a NullPointerException if it getValue()
returns null. While this will still fail your test, it won't be so obvious what went wrong.
Of course, if null values ββare not valid, you should short
not return a short
. In this case, you don't need any casts:
assertEquals(obj.getValue(), 42); // fine, if getValue() returns a short
The Short class does not have a method that takes int
as a parameter, so
Short.valueOf(1); // compilation error
but casting to (short) 1
Short.valueOf((short) 1);
works because a short method is used as a parameter. Why can't this compiler do the casting automatically because
Narrowing primitive conversions can lose information about the total value of a numeric value, and can also lose precision and range.
JLS states
An Integer literal is long if it is suffixed with an ASCII letter L or l (ell); otherwise, it is of type int (Section 4.2.1).
Therefore, you need to give it to short
.
You might also be interested in Why are there no bytes or short literals in Java?