静态初始化程序在定义之前无法引用字段 [英] Static initializer cannot reference a field before it is defined

查看:349
本文介绍了静态初始化程序在定义之前无法引用字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,错误已注释

I have the following code with the error commented

public final class MyStaticClass {

    private MyStaticClass() {}

    static {

        a = new A();
        b = new B(a);    // Cannot access a field before it is defined
    }

    private static final A a;
    private static final B b;
}

我对使用静态初始化器相当新,但我不知道为什么这不会编译。我查看了有关此主题的一些帖子,并看到了初始化运行的顺序,但这似乎并没有违反规则。当b被初始化时,应该已经有了。

I'm fairly new to using static initializers, but I have no idea why this will not compile. I've looked around a few of the posts on this topic, and have seen the order that initialisation runs, but this doesn't seem to violate the rule. By the time b is being initialized, a should already have been.

我有一个解决方法,就是将这个类设置为单例,但这样做会使代码的可读性降低一些。我很想知道这里出了什么问题。

I have a work around, which would be to set up this class as a singleton, but doing so would make the code a little less readable. I'm keen to know what is going wrong here.

推荐答案

这在 JLS 8.3.3 。事实上,有几种方法可以解决它。

This is explained in JLS 8.3.3. In fact, there are a few ways to fix it.

使用限定名称 a

// #1
public final class MyStaticClass {
    static {
        a = new A();
        b = new B(MyStaticClass.a);
    }

    private static final A a;
    private static final B b;
}

如果 a b 是在实例初始化程序中初始化的实例字段, a 可以限定为。 a

If a and b were instance fields being initialized in an instance initializer, a could be qualified as this.a.

将前向引用放在 a 的左侧赋值:

Put the forward reference to a on the left-hand of an assignment:

// #2
public final class MyStaticClass {
    static {
        b = new B(a = new A());
    }

    private static final A a;
    private static final B b;
}

当然,在参考文献之前以文字方式提交声明:

And of course put the declaration textually before the reference:

// #3
public final class MyStaticClass {
    private static final A a;
    private static final B b;

    static {
        a = new A();
        b = new B(a);
    }
}

根据JLS,#3在技术上不是必需的(这些类变量在范围内),而这是为了捕获特定类型的错误,其中字段按顺序初始化:

According to the JLS, #3 is not technically necessary ("these class variables are in scope"), rather this is designed to catch a particular kind of error where fields are initialized out of order:

public final class MyStaticClass {
    private static final B b = new B(a); // a is null
    private static final A a = new A();
}

(虽然我只是告诉你两种方法来阻止它并且无论如何都要犯错误。)

(Though I just showed you two ways to thwart it and make the error anyway.)

我建议#1或#3,因为#2有点深奥。您似乎没有犯这个规则旨在捕获的错误。

I'd recommend #1 or #3 since #2 is a bit esoteric. You don't seem to be making the error this rule is designed to catch.

这篇关于静态初始化程序在定义之前无法引用字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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