为什么尝试打印未初始化的变量并不总是会导致错误消息 [英] Why attempt to print uninitialized variable does not always result in an error message

查看:134
本文介绍了为什么尝试打印未初始化的变量并不总是会导致错误消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些人可能会发现它类似于SO问题 Will Java最终变量具有默认值?但该答案并未完全解决此问题,因为该问题不直接在实例初始化程序块中打印x的值。

Some may find it similar to the SO question Will Java Final variables have default values? but that answer doesn't completely solve this, as that question doesn't directly print the value of x within instance initializer block.

当我尝试在实例初始化程序块内直接打印x时,问题出现了,同时在块结束之前为x分配了一个值:

The problem arises when I try to print x directly inside the instance initializer block, while having assigned a value to x before the end of the block :

class HelloWorld {

    final int x;

    {
        System.out.println(x);
        x = 7;
        System.out.println(x);    
    }

    HelloWorld() {
        System.out.println("hi");
    }

    public static void main(String[] args) {
        HelloWorld t = new HelloWorld();
    }
}

这给出了编译时错误,说明变量x可能尚未初始化。

This gives a compile time error stating that variable x might not have been initialized.

$ javac HelloWorld.java
HelloWorld.java:6: error: variable x might not have been initialized
        System.out.println(x);
                           ^
1 error



案例2



我没有直接打印,而是调用打印功能:

Case 2

Instead of directly printing, I am calling a function to print:

class HelloWorld {

    final int x;

    {
        printX();
        x = 7;
        printX();
    }

    HelloWorld() {
        System.out.println("hi");
    }

    void printX() {
        System.out.println(x);
    }

    public static void main(String[] args) {
        HelloWorld t = new HelloWorld();
    }
}

这正确编译并提供输出

0
7
hi

两种情况之间的概念差异是什么?

What is the conceptual difference between the two cases?

推荐答案

在JLS中,§8.3.3。字段初始化期间的前向引用,它声明在以下情况下存在编译时错误:

In the JLS, §8.3.3. Forward References During Field Initialization, its stated that there's a compile-time error when:


使用其声明出现的实例变量使用后的文本有时受限制,即使这些实例变量
在范围内。具体来说,如果以下所有
都为真,则为编译时错误:

Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables are in scope. Specifically, it is a compile-time error if all of the following are true:


  • 声明类或接口C中的实例变量在使用实例变量后以文本方式显示;

  • The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;

在C的实例变量初始值设定项中使用是一个简单名称或C的实例初始值设定项;

The use is a simple name in either an instance variable initializer of C or an instance initializer of C;

使用不在作业的左侧;

The use is not on the left hand side of an assignment;

C是封闭使用的最里面的类或接口。

C is the innermost class or interface enclosing the use.

以下规则附带一些示例,其中最接近您的是:

The following rules come with a few examples, of which the closest to yours is this one:

class Z {
    static int peek() { return j; }
    static int i = peek();
    static int j = 1;
}
class Test {
    public static void main(String[] args) {
        System.out.println(Z.i);
    }
}

通过方法没有以这种方式检查,所以上面的代码产生输出 0 ,因为 i 使用类方法 peek() j 的值> j 已由其变量初始化程序初始化,此时它仍然具有其默认值(§4.12.5变量的初始值)。

Accesses [to static or instance variables] by methods are not checked in this way, so the code above produces output 0, because the variable initializer for i uses the class method peek() to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5 Initial Values of Variables).

总而言之,你的第二个示例编译并执行正常,因为当您调用 printX() x 变量是否已经初始化c>当 printX()实际发生在运行时, x 变量将被赋予其默认值( 0 )。

So, to summarize, your second example compiles and executes fine, because the compiler does not check if the x variable was already initialized when you invoke printX() and when printX() actually takes place at Runtime, the x variable will be assigned with its default value (0).

这篇关于为什么尝试打印未初始化的变量并不总是会导致错误消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆