最终类变量的初始化之间的区别 [英] Difference between initialization of final class variable

查看:92
本文介绍了最终类变量的初始化之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚尝试设置一个变量,向我展示了超级构造函数已经完成而没有浪费我的代码。
所以我记得如何初始化类变量;在超级构造函数之后但在类构造函数之前。
但是,如果您看下面的示例,将会有些奇怪:

I just tried out to set a variable, showing me that the super constructor has been finished without wasting my code. So I remembered how class variables are initialized; after the super constructor but before the class constructor. But there is something strange if you look at this example:

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

}

其输出如下: / p>

which has the following output:

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

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

This effect can be seen on the eclipse output as well as on running the class with javac. But the eclipse debugger shows the correct value of finalTrueA within the super constructor call of the syso method.

所以我的问题是:这种效果是正确的吗?不同的初始化会导致静态字段的行为不同,这是eclipse调试器的错误,还是这种行为是错误的,并且是Java的错误???

So my question: Is this effect correct, that the different initialization results in different behaviour of the static fields and this is a bug of the eclipse debugger, or is this behaviour incorrect and it is a bug of java???

推荐答案

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

Every final variable which is immediately assigned with a compile-time constant and has a primitive or String type is a compile-time constant as well and its value will be inlined at compile-time when used in an expression context. This does apply to all variables, not only static. Consider the following (valid) code:

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

此处,局部变量一个两个三个是编译时常量,因此甚至允许作为切换用例标签…

Here, the local variables zero, one, two, and three are compile-time constants and hence even allowed as switch case labels…

this.finalTrueA 的值在编译时内联,因此即使从超级构造函数中调用也将为 true

In you case the value of this.finalTrueA inlined at compile-time and hence will be true even when invoked from the super-constructor.

这篇关于最终类变量的初始化之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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