0

看看这个简单的 Java 代码:

final class A {
    public static void main(String[] args) {
        int x = 3;
        boolean b;
        switch(x) {
            case 1:
                b = true;
                break;
            default:
                throw new RuntimeException();
        }
        System.out.println("b: " + b);
    }
}

它在开关中分配一个b值,但在默认情况下,会引发异常。当然,在实际代码中,x会以更复杂的方式计算。

$ javac A.java && java A
Exception in thread "main" java.lang.RuntimeException
    at A.main(A.java:10)

按预期运行时失败。

有人想将这个异常抛出到一个函数中,以避免一遍又一遍地输入相同的东西:

final class A {
    private static final void f() {
        throw new RuntimeException();
    }
    public static void main(String[] args) {
        int x = 3;
        boolean b;
        switch(x) {
            case 1:
                b = true;
                break;
            default:
                f();
        }
        System.out.println("b: " + b);
    }
}

但是,这不起作用:

$ javac A.java && java A
A.java:15: variable b might not have been initialized
        System.out.println("b: " + b);
                                   ^
1 error

它抱怨b可能没有初始化,尽管它显然与前面的代码等效。为什么?

4

2 回答 2

0

编译器的代码可达性分析并非无所不知。
例如,它不会在函数调用内部检查它们是否真的可以返回。

因此,它不知道f()会抛出异常,所以它认为println()调用是可达的并抱怨它。

于 2013-05-05T02:26:07.940 回答
0

@Slaks 和@dasblinkenlight 的答案正确地指出了问题的原因。但它们都暗示(或可以理解为暗示)这是编译器或编译器编写者的错。

实际上,Java 编译器只是在执行 JLS 中指定的明确初始化规则。就是那些规则说b的不是绝对初始化的。

如果有人要实现一个“更智能”的 Java 编译器,它发现异常总是被抛出......并允许代码编译......你会遇到一个编译器接受另一个编译器认为是非法的代码的问题。这对于源代码可移植性来说是一件坏事。

底线是您的代码不会编译,因为 Java 规范说它不应该编译。

于 2013-05-05T02:40:03.550 回答