Java Singleton.getInstance()返回null?

时间:2013-03-26 21:34:14

标签: java singleton autoboxing

我正在尝试使用这个单例,但getInstance显然可以返回null:

class Singleton {
    public static final String K_LEVEL = "level";
    static Singleton instance = new Singleton();
    private int level;

    static Singleton getInstance() {
        return instance;
    }

    int getLevel() {
        return level;
    }

    void incrementLevel() {
        System.out.println("LEVEL INCREASED TO " + ++level);
    }

    void addToLevel(int x) {
        for(int i=0;i<x;i++)
            incrementLevel();
    }

}

class A {
    public static void main(String[] args) {
        Singleton s = Singleton.getInstance();
        Integer i = Integer.getInteger(Singleton.K_LEVEL);
        s.addToLevel(i);
    }
}

我听说在Java中实现单例是非常困难的,并且容易出现竞争条件。我的单例模式是否实现错误?我最近改变了我的代码看起来像这样,现在getInstance有时会返回null。为什么呢?

$ java A -Dlevel=1
Exception in thread "main" java.lang.NullPointerException
    at A.main(A.java:29)

4 个答案:

答案 0 :(得分:2)

这不是关于你的单身模式,这对我来说很好。正是Integer.getInteger(Singleton.K_LEVEL);方法返回null。我敢打赌,"level"系统属性尚未设置且为null

根据我的评论,您需要在命令行上将-Dlevel=1 放在 A类之前。如果您调试代码或打印出系统属性,您将看到它是null。

当您尝试将null传递到addToLevel(int x)并尝试将null自动取消装箱为int x时,您会收到NPE。

顺便说一句,如果多个线程使用此类,则应考虑在AtomicInteger类中使用可重入的Singleton

答案 1 :(得分:2)

java -Dlevel=1 A应该符合您的需求。

doc开始,语法为java [ options ] class [ argument ... ]-Dlevel=1被视为一个选项(请参阅options部分)。

答案 2 :(得分:2)

你的单身人士没有任何问题。没有并发问题,因为这不是多线程代码。

您以为s为空,但实际上i为空。

由于addToLevelint作为参数,Integer i被自动装箱(从Integer隐式转换为int),但自{{1} } inull被抛出。当被隐蔽的值为NullPointerException时,Autounboxing会抛出NullPointerException

null返回Integer.getInteger(Singleton.K_LEVEL)的原因是因为您null而不是java A -Dlevel=1。后者是正确的语法。

答案 3 :(得分:0)

static Singleton instance = new Singleton();应该是最终的,以防止竞争。