为什么范围内缩小的长值不会被隐式转换?

Pac*_*ier 5 java compiler-construction constants literals

当我们声明一个时static final,Java编译器(或预编译器?)似乎足够聪明,可以检测到超出范围的数字:

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;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码证明了for int,shortchar值,只有当值超出指定变量类型的范围时,编译器才会抱怨.

但是对于long值,即使数字在范围内,编译器也会抱怨:

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;
}
Run Code Online (Sandbox Code Playgroud)

为什么编译器只在范围检测智能的 int,shortchar值?

为什么编译器不对long值进行范围检测?

Mar*_*o13 4

答案可能并不令人满意,但是……

\n

Java语言规范第 5.2 节说:

\n
\n

赋值上下文允许将表达式的值 (\xc2\xa715.26) 赋给变量;表达式的类型必须转换为变量的类型。

\n

...

\n

另外,如果表达式是 byte、short、char 或 int 类型的常量表达式 (\xc2\xa715.28):

\n
    \n
  • 如果变量的类型是 byte、short 或 char,并且常量表达式的值可以用变量的类型表示,则可以使用缩小基元转换。
  • \n
\n
\n

对于编译良好的情况,常量表达式始终为 、 或 类型shortchar并且int该值可以用目标类型表示。对于long类型来说,根据规范根本不允许这样的转换。

\n
\n

答案可能并不令人满意,因为下一个明显的问题是:

\n
\n

他们为什么要这样写规范?

\n
\n

JLS 的链接部分中也给出了这个示例,这可以部分回答这个问题:这种隐式转换很可能主要用于您想要编写如下声明的情况

\n
byte b = 42;\n
Run Code Online (Sandbox Code Playgroud)\n

因为否则,您必须将int值 42 转换为字节,如下所示

\n
byte b = (byte)42;\n
Run Code Online (Sandbox Code Playgroud)\n

从这个意义上说,您想要bytelong值初始化 a 的情况并不常见。

\n