首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当成员初始化时?

当成员初始化时?
EN

Stack Overflow用户
提问于 2014-07-06 10:41:25
回答 4查看 103关注 0票数 1

考虑以下几类:

代码语言:javascript
复制
public class A {
    String bar = "A.bar";

    A() { foo(); }

    public void foo() {
        System.out.println("A.foo(): bar = " +
        bar);
    }
}


public class B extends A {
    String bar = "B.bar";

    B() { foo(); }

    public void foo() {
        System.out.println("B.foo(): bar = " +
        bar);
    }
}

public class C {
    public static void main(String[]
    args) {
        A a = new B();
        System.out.println("a.bar = "
        + a.bar);
        a.foo();
    }
}

现在,打印的第一行是:B.foo(): bar = null。据我理解,成员初始化在构造函数之前,但我可以看到这里不是这样的。

为什么在这个阶段没有初始化B#bar

何时初始化B#bar

谢谢!

更新:

阅读完你的答案后,请看下面的反例:

代码语言:javascript
复制
public class Bazz {

    public int a = 42;

    public Bazz() {
        System.out.println(a);
    }

    public static void main(String[] args) {
        Bazz bazz = new Bazz();
    }
}

在这种情况下,a不是0。相反,Bazz()的构造函数打印42

有什么关系呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-07-06 11:12:27

让我列举以下步骤:

  • A a = new B(); //它看到B是so调用A的构造函数的子函数(B.bar尚未初始化)
  • 在A的构造函数中,调用foo。因为它已经被B覆盖,所以B的foo被调用并显示为null。
  • 在A的构造函数完成后,B.bar被初始化。
  • 然后调用B的构造函数。

注意:即使B中没有调用super(),编译器也会自动添加此语句。

编辑:编译器如何查看B的构造函数:

超级(); this.bar = "B.bar"; foo();

UPDATE:您的新结果来自我前面给出的相同解释:

  • Bazz bazz = new Bazz(); //当调用构造函数时,变量a被初始化为42

  • System.out.println(a); //印刷品42

实例变量在执行构造器之前,但是在超级构造器执行之后,都是不对称的。请参阅我上面的编辑。

票数 3
EN

Stack Overflow用户

发布于 2014-07-06 10:56:04

您正在通过new B()进行构造,在构造函数B()中,它调用super()

因此,您的代码调用A a = new B();,这属于System.out.println("B.foo(): bar = " + bar);。此时,a尚未完成构造(未完全初始化),因此B.barnull。当构造函数命中= "B.bar"时,= "B.bar"将初始化}

TL;DR:

为什么在这个阶段没有初始化B#bar

因为a没有在System.out.println("B.foo(): bar = " + bar);上被完全初始化。

何时初始化B#bar

} (Constructor end)

为了记录在案,这里有STDOUT日志:

B.foo():bar = null // bar未初始化。我们在:A() { foo(); } B.foo():bar = B.bar // bar被初始化。我们在:B() { foo(); } a.bar = A.bar //您调用"println a.bar = a.bar“。在A a中,bar等于a.bar。 B.foo():bar = B.bar // foo()是多态的,由于aclass B,所以调用了B.foo(),因此这一行。

@编辑: Bazz.a的类型为intint永远不会是null,编译器会自动将这些变量作为编译器传递来替换您的语句。于是System.out.println(a);变成了System.out.println(42);

票数 1
EN

Stack Overflow用户

发布于 2014-07-06 10:51:32

当您从类创建对象时,静态初始化器首先运行.

它初始化静态属性和静态方法,

然后运行对象初始化程序,

首先,它运行对象B()的构造函数,

因此,非静态属性(bar)将在稍后初始化.因此,属性在执行构造函数后正在初始化。所以bar是null

如果你宣布酒吧是静态的,

代码语言:javascript
复制
static String bar = "B.bar";

您可以先初始化bar变量;

输出为;

B.foo():bar = B.bar

B.foo():bar = B.bar

a.bar = A.bar

B.foo():bar = B.bar

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24594988

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档