Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java weird assignment rules

short s = 'a';       // valid
Short ss = 'a';      // valid
int i = 'a';         // valid
Integer ii = 'a';    // invalid

Why Integer ii = 'a' invalid, but int i = 'a' valid? Why Short ss ='a' valid, but Integer ii = 'a' invalid?


another set question:

byte b;
final short s = 1;
final Short ss = 1;
final int i =1;
final Integer ii = i;
final long L = 1;
final Long LL =1L;

b = s;     // valid
b = ss;    // invalid
b = i;     // valid
b = ii;    // invalid
b = L;     // invalid
b = LL;    // invalid  

Why b = L; invalid, while b = s; valid ?

Please, don't say it is all because JLS said so. I want to know why JLS has these inconsistent and non-intuitive rules. What did I miss?

like image 232
Vincent Quan Avatar asked Apr 13 '17 18:04

Vincent Quan


1 Answers

So, the line:

Short s = 'a'; // is valid ...

Because char is unsigned 16-bit value (maximum value is 65,536) and short is signed 16-bit value (maximum value is 32,767), so there is a narrowing primitive conversion (char to short) followed by a boxing conversion (short to Short).

short s = 'a'; // is valid - this is a narrowing primitive conversion (char -> short)

These are special cases:

In addition, if the expression is a constant expression 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.

Let's go to the next examples:

Integer ii = 'a'; // is invalid - not a special case according to Oracle docs
int i = 'a';      // is valid - widening primitive conversion (char -> int) is allowed

And one more case from your question:

byte b;
final long L = 1;
b = L // error - incompatible types

Why the line b = L is invalid? Because it isn't a special case described above and we can lose information during a cast, that's why you must perform it explicitly:

b = (byte) L; // is valid - narrowing primitive conversion (long -> byte)

Also, have a look into a very helpful table.

There are a lot of information about all these rules in the JLS documentation and you don't need to worry about all of them. What can I say about your last question is that without an implicit narrowing conversion any integer literal would require a cast in the next cases:

// Cast is permitted, but not required - profit!
byte  b = (byte)  100;
short s = (short) 100;

Thanks to that we can change it to:

byte  b = 100;
short s = 100;
like image 189
Oleksandr Pyrohov Avatar answered Nov 06 '22 18:11

Oleksandr Pyrohov