Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I assign an integer literal to a short type variable but not to a short type method parameter?

Why can I do this:

short a = 5;

But not this:

void setNum(short a);

setNum(5);

It throws:

Possible lossy conversion from int to short

I understand that 5 is an integer literal and you have to cast it. I also understand that if the value is not a constant then is obvious that it needs to throw that error because maybe the value reaches the limit of a short type. But why if the compiler knows I'm passing a constant that a short can hold (as in the assignment) it doesn't let it compile? I mean, what is the difference between them?

like image 887
GabrielBB Avatar asked Oct 06 '16 01:10

GabrielBB


1 Answers

In order to understand why the assignment type-conversion works whilst the invocation one is rejected, one has to refer to the Java Language Specification topic for both narrowing primitive conversions and the context of that conversion: assignment context and invocation context.

According to the JLS, the narrowing primitive conversion is allowed in assignment context if:

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.

... which matches your case with int constant 5 when assigned to short a.

No such narrowing primitive conversion is allowed in the invocation context, which explains why your call to setNum(short) fails when passed the int constant 5.

But why if the compiler knows I'm passing a constant that a short can hold (as in the assignment) it doesn't let it compile? I mean, what is the difference between them?

The JLS must not have wanted to burden compilers with this additional logic. In the invocation case, the argument which is type-matched to the formal parameter is an expression - the compiler already has to determine the type, but it shouldn't need to also check if the expression's value can also safely be narrowed. In this case, being a constant, it is clear to us that it can be, but in execution context the compiler is allowed to not bother with that check, and is in-fact correct to disallow it.

It should be fairly clear that when expressions are allowed, it would be much easier for bugs to creep in where narrowing cannot be done without losing precision, so the JLS and compilers just disallow it in all cases.

The same is true in numeric context, so the declaration:

short a = 5;short b = a * 5;

... is similarly not allowed, despite being clearly comprised of constants which narrow correctly.

like image 111
javabrett Avatar answered Oct 12 '22 13:10

javabrett