java - 为什么Java编译器不理解这个变量总是被初始化?

标签 java initialization conditional final

class Foo{
    public static void main(String args[]){
        final int x=101;

        int y;
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

Java 编译器理解 if 语句的条件始终为真,因此 y 将始终被初始化。正如预期的那样,没有编译错误。

class Bar{
    public static void main(String args[]){
        final int x;
        x=101;

        int y;      
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

但是当我将 x 的声明和初始化分成两行时,编译器似乎没有得到条件始终为真并且 y 将始终被初始化。

final int x;
x=101;
byte b;
b=x;
System.out.println(b);

同样的事情发生在这里,编译器给出了精度损失错误。

final int x=101;
byte b;
b=x;
System.out.println(b);

再次,编译器可以理解 x 在 b 的范围内。

最佳答案

作为实现可移植性目标的一部分,对于编译器应该接受什么和应该拒绝什么有一套非常具体的规则。在确定变量在使用时是否被明确分配时,这些规则既允许也只需要有限形式的流分析。

参见 Java 语言规范 Chapter 16. Definite Assignment

关键规则是 16.2.7. if Statements 中的规则。 ,“如果(e)S”的情况。明确分配的规则扩展为:

Vif (e) S 之后赋值当且仅当 VS 之后赋值> 和 Ve 之后赋值为 false。

y 是相关的V。它在 if 语句之前未分配。它确实是在 S, y = {y=-1;} 之后分配的,但是当 x>100 为 false 时,没有任何东西使它分配。

因此 y 不是在 if 语句之后明确分配的。

更完整的流程分析将确定条件 x>100 始终为真,但 JLS 要求编译器根据这些特定规则拒绝程序。

最终变量很好。规则实际上是:-

"It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment."

声明使其绝对未赋值,即使是有限流分析也可以确定 x 在赋值时仍然绝对未赋值。

关于java - 为什么Java编译器不理解这个变量总是被初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13235559/

相关文章:

java - Java 的侵入式列表实现?

java - 如何在 Ant 条件中使用脚本的输出

JSF ui :repeat included by ui:include wrapped in h:panelGroup with conditional rendering. ..一口

java - OpenGL 着色器?

java - 我的代码是线程安全的吗?如果没有的话如何实现线程安全?

java - 用于登录 Web 应用程序的语音识别

struct - 使用 slice 数据初始化结构

youtube - 安卓 11 YouTubeAndroidPlayerApi 不工作

.net - 使用 WCF 服务连接到 AppInitialize

makefile - 如何有条件地为Makefile(BSD + GNU)中的变量赋值?