Java 为什么范围内的窄长值不能隐式转换?
当我们声明一个Java 为什么范围内的窄长值不能隐式转换?,java,compiler-construction,constants,literals,Java,Compiler Construction,Constants,Literals,当我们声明一个静态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; publi
静态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;
}
上面的代码证明,对于int
、short
和char
值,编译器仅在值超出指定变量类型的范围时才会进行投诉
但是,对于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;
}
为什么编译器只能在范围检测时对int
、short
和char
值进行智能操作
为什么编译器不对长值进行范围检测?答案可能不令人满意,但
报告说:
赋值上下文允许将表达式的值赋值(§15.26)给变量;表达式的类型必须转换为变量的类型
此外,如果表达式是byte、short、char或int类型的常量表达式(§15.28):
- 如果变量的类型是byte、short或char,并且常量表达式的值可以在变量的类型中表示,则可以使用窄化原语转换
对于编译良好的情况,常量表达式的类型始终为short
、char
或int
,并且该值可在目标类型中表示。对于long
类型,根据规范,这样的转换是不允许的
答案可能并不令人满意,因为下一个明显的问题是:
他们为什么这样写规范
JLS链接部分给出的示例可能部分回答了这一问题:此隐式转换很可能主要用于您希望编写如下声明的情况
byte b = 42;
因为否则,您必须将int
值42转换为字节,如中所示
byte b = (byte)42;
从这个意义上讲,您希望从long
值初始化字节的情况并不常见。编译器之所以这样做,是因为较旧的java设计,并且仅在有限的范围内(-128-127)。加宽效果很好。@Hannes,是的,加宽很好(因为它很好,总是在范围内)。奇怪的是变窄的部分。仅当缩小的值为int
、short
或char
类型时,范围检测才会激活。