Why are the narrowed long values ​​at the far end implicitly converted?

When we declare static final , the Java compiler (or the preliminary compiler?) Seems smart enough to detect numbers out of range:

 public class Test { // setup variables: public static final int i_max_byte = 127; public static final int i_max_byte_add1 = 128; public static final int i_max_short = 32767; public static final int i_max_short_add1 = 32768; public static final int i_max_char = 65535; public static final int i_max_char_add1 = 65536; public static final char c_max_byte = 127; public static final char c_max_byte_add1 = 128; public static final char c_max_short = 32767; public static final char c_max_short_add1 = 32768; public static final short s_min_char = 0; public static final short s_min_char_sub1 = -1; public static final short s_max_byte = 127; public static final short s_max_byte_add1 = 128; // all these are OK: public static final byte b1 = i_max_byte; public static final byte b2 = s_max_byte; public static final byte b3 = c_max_byte; public static final byte b4 = (short) i_max_byte; public static final byte b5 = (char) i_max_byte; public static final char c1 = i_max_char; public static final char c2 = s_min_char; public static final short s1 = i_max_short; public static final short s2 = c_max_short; // pre-compiler complains "type-mismatch": public static final byte _b1 = i_max_byte_add1; public static final byte _b2 = s_max_byte_add1; public static final byte _b3 = c_max_byte_add1; public static final byte _b4 = (short) i_max_byte_add1; public static final byte _b5 = (char) i_max_byte_add1; public static final char _c1 = i_max_char_add1; public static final char _c2 = s_min_char_min_us1; public static final short _s1 = i_max_short_add1; public static final short _s2 = c_max_short_add1; } 

The above code proves that for int , short and char values, the compiler only complains when the value is out of range for the type of the assigned variable.

However, for long values, the compiler complains even if the numbers are within the range:

 public class Test2 { public static final long l_max_byte = 127; public static final long l_max_byte_add1 = 128; public static final long l_max_char = 32767; public static final long l_max_char_add1 = 32768; public static final long l_max_short = 65535; public static final long l_max_short_add1 = 65536; public static final long l_max_int = 2147483647; public static final long l_max_int_add1 = 2147483648L; // "type-mismatch" for all: public static final byte b1 = l_max_byte; public static final byte b2 = l_max_byte_add1; public static final char c1 = l_max_char; public static final char c2 = l_max_char_add1; public static final short s1 = l_max_short; public static final short s2 = l_max_short_add1; public static final int i1 = l_max_int; public static final int i2 = l_max_int_add1; } 

Why is the compiler only smart when it detects a range for int , short and char ?

Why doesn't the compiler detect a range for long values?

+5
source share
1 answer

The answer may be unsatisfactory, but ...

The Java Language Specification, Section 5.2 , says:

Destination contexts allow you to assign the value of an expression (Β§15.26) to a variable; the type of the expression must be converted to the type of the variable.

...

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

  • Narrowing the primitive conversion can be used if the type of the variable is a byte, short, or char, and the value of the constant expression is represented in the type of the variable.

For cases that compile fine, the constant expression is always of type short , char or int , and the value is represented in the target type. For the long type, such a conversion is simply forbidden according to the specification.


The answer may be unsatisfactory because the following obvious question:

Why do they write such a specification?

This can be partially answered by an example, which is also indicated in the associated JLS section: this implicit conversion is most likely intended for the case when you want to write an ad like

 byte b = 42; 

because otherwise you would need to output the int value of 42 to bytes, as in

 byte b = (byte)42; 

The case that you want to initialize with the byte value from the long value is not so common in this sense.

+3
source

Source: https://habr.com/ru/post/1202039/


All Articles