属性初始化Java

属性初始化Java,java,constructor,Java,Constructor,我正在收集一份个人备忘单的设计模式,我发现了一段奇怪的代码,至少对我来说是这样,它是头先设计模式(由Eric Freeman、Elisabeth Robson、Bert Bates、Kathy Sierra编写) 我不认为我被允许在这里发布这本书中所写的代码,但我将重现让我震惊的代码: 假设我们以前使用一个公共方法runSomeCode()定义了类A,那么类B如下所示: public class B { A a; A b; A x = a; public B(

我正在收集一份个人备忘单的设计模式,我发现了一段奇怪的代码,至少对我来说是这样,它是头先设计模式(由Eric Freeman、Elisabeth Robson、Bert Bates、Kathy Sierra编写)

我不认为我被允许在这里发布这本书中所写的代码,但我将重现让我震惊的代码:

假设我们以前使用一个公共方法runSomeCode()定义了类
A
,那么类B如下所示:

public class B {

    A a;
    A b;
    A x = a;

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

    public void testB()
    {
        x.runSomeCode();
    }    
}
我看这段代码的第一印象是,任何对B实例testB方法的调用都应该抛出一个
NullPointerException
,但我无法想象他们会发布这样一个错误

如果这本书是对的,那么我理解这一点

x = a;
必须在B构造函数执行结束时完成,但我仍然对此感到惊讶,我的问题是:

  • 我错了吗
  • Java总是这样吗
  • 在这种情况下(我个人认为这有点混乱):它是否可能在未来的java版本中被删除?
  • 你会尽量避免吗
编辑这是本书的示例:

我关心的情况是numberGumballs=0

编辑II

我想我知道这个例子发生了什么

在书中,引用的类是而不是声明为静态的,但几分钟前我认为如果A是静态的,它可以编译。因此,这本书的作者可能从一个使用静态类的更大项目中获得了代码。所以我尝试了这个,这一次,它确实起了作用,但是这个例子似乎仍然是错误的,下面的代码没有任何意义

又一次编辑

我似乎不是第一个在书中注意到这个问题的人, 在网站上,您可以找到:

我错了吗

就地变量初始化在构造函数中初始化之前工作,其顺序与代码中定义的变量相同

Java总是这样吗

在这种情况下(我个人认为这有点令人困惑): 它可能会在未来的Java版本中被删除吗

不,Java是向后兼容的语言,这是基本的,不会更改

你会尽量避免吗


如果需要就地初始化,请确保它独立于其他变量的初始化。否则在构造函数中初始化它。不要进行复杂的就地初始化。

要回答您的问题:

  • 我相信你错了,根据字段初始化器是在构造函数体之前执行的
  • 我相信它有,但不想检查每个版本的规范。不过我不知道有什么变化
  • 我对此表示怀疑,因为它是规范的一部分,如果他们更改了它,会破坏兼容性。但是
  • 在这种情况下,通过将赋值移动到
    x
    到构造函数中,可以很容易地将代码更改为显式说明初始化顺序。将其作为字段初始值设定项并没有明显的好处

  • 这种“模式”的意义何在?您只需使用两个引用就可以了……为什么不直接使用
    a
    呢?

    当您第一次创建类型为B的对象时,具有任何初始化的字段都会首先初始化。所以,
    ax=A首先执行,甚至在构造函数中的代码执行之前执行,该代码将x的值设置为null,因为a尚未实例化,只是类型a的null引用。在此之后,执行以下代码,创建两个对象

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

    此时x仍然为空。因此,当您尝试使用x在类中执行方法时,它将抛出空指针异常。

    它肯定会抛出NPE,您可以(实际上)尝试它。@m0skit0您是对的,我在深夜测试了该案例,可能做了一些不同的事情。然而,书中的例子是这样的,所以书是错的,或者我是瞎子/白痴书中的例子是错的,有时会发生;)我同意。看来你在书的代码中发现了一个错误。这是一个笑话,这本书太棒了。我在问题中已经说过,就我所知,它毫无意义。另一方面,我在深夜测试了它,我想我可能做了一些不同的事情,但我会尝试复制它。我在问题中已经说过,就我所知,它毫无意义。另一方面,我在深夜测试了它,我想我可能做了一些不同的事情,但我会尝试复制它。
    public B() {
        a = new A();
        b = new A();
    }