整型转换为字节无法编译

6

我有两个几乎相同的程序,一个可以编译,另一个不行。为什么?

我将一个int变量赋值给了一个byte变量。

这个可以编译:

class Example {
    public static void main(String args[]) {
        final int x = 127; // directly initialized

        byte b;
        b = x;

        System.out.println(b);
    }
}

这个无法编译:

class Example {
    public static void main(String args[]) {
        final int x;
        x = 127; // assigned later

        byte b;
        b = x;

        System.out.println(b);
    }
}

编译器在b = x;处显示类型不兼容。但是第一个版本不也应该是这样吗?

3
请编辑您的问题并添加您收到的错误信息。 - Progman
1
编译时出现了什么错误? - Nikolas Charalambidis
1
这个回答解决了你的问题吗?“可能有损转换”是什么意思,我该如何解决?(https://dev59.com/DFUK5IYBdhLWcg3wjwqY) - Progman
@Progman,那些答案并没有解决我的问题。 - Virangaa
下次请展示完整的错误信息,包括行数等。 - Zabuzard
1
@Progman 不是重复的。虽然最初的问题表述不是很清楚,但现在很明确OP在问什么,实际问题是什么。 - Zabuzard
1个回答

9

这个问题很难懂,真的很难懂。

第一个版本有效是因为JLS在§5.2中规定,如果一个int值是常量表达式且在-128到+127之间,则可以将其赋值给byte变量。而常量变量是一个常量表达式,而final int x = 127;则声明了一个常量变量

第二个版本无法运行,原因是final int x;没有声明一个常量变量。JLS在§4.12.4中表示:

常量变量是指用常量表达式(§15.28)初始化的基本类型或String类型的final变量。

在第二个版本中,final变量有一个空的初始化器,然后被后面赋值。结果就是§5.2中允许收缩原始常量的规则是不被允许的。


为什么不能将final int x;视为编译时常量呢?

考虑以下内容:

    final int x;
    if (something) {
        x = 127;
    } else {
        x = 1023;
    }
    byte b = x;

初始化b是否应该被允许,还是会导致"损失"转换?这取决于something的值。

假设情况下,在上面的示例的某些变体中,编译器可以决定所有可能的x值都可以正常工作,但是增加编译器和语言规范的复杂性是不可辩解的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接