Static initializer cannot reference a field before it is defined

时光总嘲笑我的痴心妄想 提交于 2019-12-10 10:58:33

问题


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;
}

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.


回答1:


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

Use a qualified name of 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;
}

If a and b were instance fields being initialized in an instance initializer, a could be qualified as this.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);
    }
}

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.)

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.




回答2:


You can't use a in your static block when it hasn't been declared yet. So declare it before the static block:

public final class MyStaticClass {

    private MyStaticClass() {}

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

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

}

(I assumed that calling your instance of A "b" and your instance of B "a" was a typo.)




回答3:


Static initialization is done in the order it's written in the code. So in your code it will enter the static block first and then will go to the variable declaration...

you cant use a variable before it is declared and thats why it wont compile...

public final class MyStaticClass {

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

    private MyStaticClass() {}

    static {

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


}



    }


来源:https://stackoverflow.com/questions/26784924/static-initializer-cannot-reference-a-field-before-it-is-defined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!