我当时正在收集个人备忘单的设计模式,至少在我看来,在Head First Design Patterns(由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是静态的,则可以编译。因此,也许,书的作者是从一个使用静态类的更大项目中获得代码的。所以我尝试了一下,这次,它确实起作用了,但是该示例似乎仍然是错误的,并且以下代码对State pattern没有任何意义。
    public class B {
    
        public static class Base {
            public static void runSomeCode() { System.out.println("Base!"); }
        }
    
        public static class A extends Base {
            public static void runSomeCode() { System.out.println("A!"); }
       };
    
        A a;
        A b;
        A x = a;
    
        public B() {
            a = new A();
            b = new A();
        }
    
        public void testB()
        {
            x.runSomeCode();
        }
    }
    

    另一个编辑

    在本书示例中,我似乎并不是第一个注意到此问题的人,
    O'Reilly site errata section, under unconfirmed erratas sub-section您可以找到:

    最佳答案

    要回答您的问题:

  • 我相信您是错的,根据Java 8 Specification字段初始化程序是在构造函数体之前执行的。
  • 我相信它已经存在,但是并不想遍历每个版本的规范。我不知道有什么变化。
  • 我对此表示怀疑,因为它是规范的一部分,如果他们对其进行更改,将会破坏兼容性。但是
  • 在这种情况下,可以通过将对x的分配移动到构造函数中,轻松地将代码更改为明确说明初始化的顺序。将其作为字段初始值设定项对我来说没有任何好处。

  • 这个“模式”的重点是什么?您仅得到两个本来可以做的引用...为什么不只使用a呢?

    10-04 13:03
    查看更多