最终类变量的初始化之间的区别

Sch*_*lli 5 java variables final initialization class

我只是试着设置一个变量,告诉我超级构造函数已经完成而没有浪费我的代码.所以我记得如何初始化类变量; 在超级构造函数之后但在类构造函数之前.但是如果你看一下这个例子,有一些奇怪的事情:

public class Init {

    public Init() {
        System.out.println("Init instance of " + this.getClass().getSimpleName());
        System.out.println("syso Init:");
        this.syso(false);
    }

    protected void syso(boolean childCall) {
        System.out.println("should not be printed because the method is overwitten");
    }

    public static class Child extends Init {

        private final boolean finalTrueA = true;
        private final boolean finalTrueB;
        private final boolean finalTrueC;

        private boolean nonFinalTrueA = true;
        private boolean nonFinalTrueB;
        private boolean nonFinalTrueC;

        {
            this.finalTrueB = true;
            this.nonFinalTrueB = true;
        }

        public Child() {
            super();
            this.finalTrueC = true;
            this.nonFinalTrueC = true;

            System.out.println("\n\nsyso Child:");
            this.syso(true);
        }

        @Override
        protected void syso(boolean childCall) {
            System.out.println("finalTrueA " + this.finalTrueA + " should be " + childCall);
            System.out.println("finalTrueB " + this.finalTrueB + " should be " + childCall);
            System.out.println("finalTrueC " + this.finalTrueC + " should be " + childCall);

            System.out.println();

            System.out.println("nonFinalTrueA " + this.nonFinalTrueA + " should be " + childCall);
            System.out.println("nonFinalTrueB " + this.nonFinalTrueB + " should be " + childCall);
            System.out.println("nonFinalTrueC " + this.nonFinalTrueC + " should be " + childCall);
        }
    }

    public static void main(String[] args) {
        @SuppressWarnings("unused")
        Child child = new Child();
    }

}
Run Code Online (Sandbox Code Playgroud)

其输出如下:

Init instance of Child
syso Init:
finalTrueA true should be false // <-- why??????????
finalTrueB false should be false
finalTrueC false should be false

nonFinalTrueA false should be false
nonFinalTrueB false should be false
nonFinalTrueC false should be false


syso Child:
finalTrueA true should be true
finalTrueB true should be true
finalTrueC true should be true

nonFinalTrueA true should be true
nonFinalTrueB true should be true
nonFinalTrueC true should be true
Run Code Online (Sandbox Code Playgroud)

可以在eclipse输出以及使用javac运行类时看到此效果.但是eclipse调试器在syso方法的超级构造函数调用中显示了finalTrueA的正确值.

所以我的问题:这个效果是否正确,不同的初始化会导致静态字段的不同行为,这是eclipse调试器的一个错误,或者这个行为是不正确的,它是java的一个bug?

Hol*_*ger 1

每个final立即分配编译时常量并具有基元或String类型的变量也是编译时常量,并且当在表达式上下文中使用时,其值将在编译时内联。这确实适用于所有变量,而不仅仅是static。考虑以下(有效)代码:

\n\n
public static void main(String[] args)\n{\n  final int zero=0, one=zero+1, two=one+one, three=two+one;\n  switch(args.length)\n  {\n    case zero: System.out.println("no args"); break;\n    case one: System.out.println("one arg"); break;\n    case two: System.out.println("two args"); break;\n    case three: System.out.println("three args");\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里,局部变量zeroonetwothree是编译时常量,因此甚至允许作为switch caselabels\xe2\x80\xa6

\n\n

在您的情况下,内联的值this.finalTrueA在编译时,因此true即使从超级构造函数调用时也是如此。

\n