Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么范围内的窄长值不能隐式转换?_Java_Compiler Construction_Constants_Literals - Fatal编程技术网

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
类型时,范围检测才会激活。