为什么两个程序有前向引用错误而第三个没有?

Mar*_*tin 53 java static instance forward

以下内容无法编译,给出"非法转发引用"消息:

class StaticInitialisation {

    static
    {
        System.out.println("Test string is: " + testString);
    }

    private static String testString;

    public static void main(String args[]) {
        new StaticInitialisation();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,以下编译:

class InstanceInitialisation1 {

    {
        System.out.println("Test string is: " + this.testString);
    }

    private String testString;

    public static void main(String args[]) {
        new InstanceInitialisation1();
    }
}
Run Code Online (Sandbox Code Playgroud)

但以下内容无法编译,给出"非法转发引用"消息:

class InstanceInitialisation2 {

        private String testString1;

    {
        testString1 = testString2;
    }

    private String testString2;

    public static void main(String args[]) {
        new InstanceInitialisation2();
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么StaticInitialisation和InstanceInitialisation2不能编译,而InstanceInitialisation1呢?

Jon*_*eet 57

这由JLS 第8.3.3节涵盖:

使用声明在使用后以文本形式出现的类变量有时会受到限制,即使这些类变量在范围内(第6.3节).具体来说,如果满足以下所有条件,则为编译时错误:

  • 在使用类变量之后,类或接口C中的类变量声明以文本形式出现;

  • 在C的类变量初始化程序或C的静态初始化程序中使用是一个简单的名称;

  • 使用不在作业的左侧;

  • C是封闭使用的最内层类或接口.

使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此.具体来说,如果满足以下所有条件,则为编译时错误:

  • 在使用实例变量之后,类或接口C中的实例变量的声明以文本形式出现;

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

  • 使用不在作业的左侧;

  • C是封闭使用的最内层类或接口.

在你的第二种情况下,使用不是一个简单的名称 - 你this明确地说.这意味着它不符合上面引用的第二个列表中的第二个项目符号,因此没有错误.

如果您将其更改为:

System.out.println("Test string is: " + testString);
Run Code Online (Sandbox Code Playgroud)

...然后它将无法编译.

或者在相反的方向,您可以将静态初始化程序块中的代码更改为:

System.out.println("Test string is: " + StaticInitialisation.testString);
Run Code Online (Sandbox Code Playgroud)

奇怪,但这就是它的方式.