1
public class Test1 {
    static final int i;
    static{
        if(3<2){
        i = 0;
        }
    }   
}
public class Test2 {
    static final int i;
    static{
        if(3>2){
        i = 0;
        }
    }   
}

Test1编译失败,类Test2编译成功。

任何人都可以告诉我编译器如何在 if 条件下评估表达式吗?

4

4 回答 4

5
static final int i;

需要在静态初始化器中初始化,因为它是最终的。

static{
        if(3<2){
        i = 0;
        }
    }

由于 3<2 文字或常量,编译器能够检测到代码的死部分并且不初始化 i.

添加一个else案例并在i那里进行一些初始化。

于 2012-12-09T10:00:33.690 回答
2

它与编译器如何确定是否执行语句有关。它在JLS #16中定义:

当发生对其值的任何访问时,每个局部变量和每个空白最终字段都必须具有明确分配的值。

在您的示例中,编译器可以确定i是(或不是)在编译时明确分配,因为中的表达式if是一个常量表达式

JLS #15.28定义了常量表达式

编译时常量表达式是表示原始类型值或字符串的表达式,它不会突然完成并且仅使用以下内容组成:

  • 原始类型的文字 [...]
  • 关系运算符 <、<=、> 和 >= [...]

有趣的是,尽管 Test2 可以编译,但 Test2 的这个修改版本无法编译:

static class Test3 {
    static final int i;
    static {
        int j = 3;
        if (j > 2) {
            i = 0;
        }
    }
}

原因是它j > 2不再是一个常量表达式。制作 jfinal将使类再次编译。

于 2012-12-09T10:06:27.803 回答
2

根据Java 语言规范,if 语句的条件部分中的表达式是编译时表达式。在 Test1 编译器知道我永远不会被初始化,这就是它抱怨的原因。在第二种情况下,编译器知道 i 将被初始化。如果你用更动态的东西替换你的编译时表达式,这两个类都将无法编译,因为编译器将无法保证 i 已初始化。

于 2012-12-09T10:08:49.440 回答
0

if (3<2)可以优化,if (false)因此 Java 编译会检测到无法访问的语句(错误)。

if (3>2)可以优化为if (true),然后始终执行包含的语句。没问题。

编译器可以很容易地检测到这些是常量标量,因此可以在编译时评估(即优化)表达式。我们期望从一个体面的编译器那里得到什么。

于 2012-12-09T11:15:52.643 回答