我从其他语言来到Java,所以如果这很明显,请原谅我,但我遇到了一个非常奇怪的行为。
我正在编写一个简单的Pig UDF。我正在返回一个Tuple对象,我使用TupleFactory单例创建。在以下两个代码示例中,第一个示例有效,而第二个示例在创建newTuple
时抛出NullPointerException;
public class MyUDF {
public Tuple func(Tuple input) {
return TupleFactory.getInstance().newTuple(Arrays.asList(o1, o2, o3));
}
}
public class MyUDF {
...
TupleFactory _factory;
public Tuple func(Tuple input) {
_factory.getInstance();
return _factory.newTuple(Arrays.asList(o1, o2, o3));
}
}
答案 0 :(得分:1)
您的第一个代码TupleFactory.getInstance()
正在调用类本身的静态类方法,正如Singleton模式实现所期望的那样。
你的第二个代码_factory.getInstance()
正在调用一个实例变量,一个已定义但尚未实例化的类成员。您不能在不存在的对象上调用对象方法。
Enum
为Singleton 最后,在Java中实现Singleton模式的最安全最简单的方法是通过枚举。搜索Stack Overflow和/或搜索引擎,例如:Java singleton enum Joshua Bloch“Effective Java”。
public enum TupleFactory {
INSTANCE;
// Add private constructor if needed.
public Tuple makeTuple( … ) {
…
return tuple ;
}
}
使用它很简单。
Tuple t = TupleFactory.INSTANCE.makeTuple( … ) ;
最后,我将添加对 Singleton 的强制性警告,这通常是一种“代码味道”,这是由于缺乏对面向对象编程的理解而导致设计不良的症状。
答案 1 :(得分:0)
你必须存储_factory.getInstance();输出第一 如 Tupleinstanceclass obj = _factory.getInstance(); return obj.newTuple(Arrays.asList(o1,o2,o3));
答案 2 :(得分:0)
我认为你应该改为
public class MyUDF {
...
TupleFactory _factory;
public Tuple func(Tuple input) {
_factory = TupleFactory.getInstance();
return _factory.newTuple(Arrays.asList(o1, o2, o3));
}
}
答案 3 :(得分:0)
从您的第一段代码中,我可以推断出getInstance()
方法是static
。关于static
方法的重要注意事项是您不应该使用Class对象访问它们。相反,您应该使用类名访问它们,因为它们是类方法。
使用singletons
背后的基本思想是,您最初没有该类的对象,并且您正在调用类方法(不是实例方法)来获取那个班的对象。现在你的第一段代码证明了这一点,但是在代码的第二部分,你已经有了_factory
个对象,那你为什么要调用getInstance()
来获取类的对象。
同样在这一行_factory.getInstance()
中,请注意_factory
刚刚被宣布,但从未初始化,这就是你获得NullPointerException
的原因。
另见:
以下代码可以使用。
public class MyUDF {
TupleFactory _factory;
public Tuple func(Tuple input) {
_factory = TupleFactory.getInstance();
return _factory.newTuple(Arrays.asList(o1, o2, o3));
}
}