我正在为个人备忘单收集设计图案,我在头部设计模式(由Eric Freeman,Elisabeth Robson,Bert Bates,Kathy Sierra)发现了至少对我来说奇怪的代码< / em>的
我不认为我可以在这里发布完整的代码片段,但是我会重现让我震惊的代码:
假设我们之前使用公共方法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构造函数执行结束时完成,但我仍然对这个sintaxis感到惊讶,我的问题是:
编辑这是本书的例子:
我担心的情况是numberGumballs = 0;
编辑II
我想我知道这个例子发生了什么。
在本书中,引用的类是 NOT 声明为静态,但几分钟前,我认为如果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你可以找到:
答案 0 :(得分:1)
我错了吗?
就地变量初始化在构造函数初始化之前工作,其顺序与代码中定义的变量相同。
Java总是表现得像这样吗?
是
在那种情况下(我个人认为这有点令人困惑):是 它可能会在未来的Java版本中删除吗?
不,Java是向后兼容的语言,这是基本的,不会改变。
你会试着避免吗?
如果您想要就地初始化,请确保它与其他变量的初始化无关。否则在构造函数中初始化它。不要进行复杂的就地初始化。
答案 1 :(得分:1)
回答你的问题:
x
到构造函数中,轻松地将代码转换为显式地说明初始化的顺序。将它作为字段初始化程序没有任何好处,这对我来说是显而易见的。这应该是什么&#34;模式&#34;?你最后会得到两个参考文献,其中一个人会做...为什么不只是使用a
?
答案 2 :(得分:1)
首次创建B类型的对象时,首先初始化具有任何初始化的字段。因此,首先执行A x = a;
,甚至在执行构造函数中的代码之前执行,该代码将x的值设置为null,因为尚未实例化并且只是类型A的空引用。在此之后,以下执行代码创建两个对象。
public B() {
a = new A();
b = new A();
}
此时x仍为null。因此,当您尝试使用x在A类中执行方法时,它将抛出空指针异常。