Java Singleton有时会抛出NullPointerException

时间:2016-11-01 05:55:29

标签: java singleton

我从其他语言来到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));
    }
}

4 个答案:

答案 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

最后,我将添加对 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的原因。

另见:

  1. What is the difference between class and instance methods?
  2. Java: when to use static methods
  3. 以下代码可以使用。

    public class MyUDF {
        TupleFactory _factory;
    
        public Tuple func(Tuple input) {
            _factory = TupleFactory.getInstance();
            return _factory.newTuple(Arrays.asList(o1, o2, o3));
        }
    }