Java Singleton.getInstance()返回null吗?

问题描述 投票:7回答:4

我正在尝试使用此单例,但是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)
java singleton autoboxing
4个回答
3
投票

您的Singleton没有错。没有并发问题,因为这不是多线程代码。

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

由于addToLevelint作为参数,所以Integer i被自动拆箱(从Integer隐式转换为int),但是由于inull,因此抛出了NullPointerException。当要掩盖的值为NullPointerException时,自动拆箱操作将引发null

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


3
投票

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

java A -Dlevel=1

您需要在命令行上放置-Dlevel=1 之前 A类。如果您调试代码或打印出系统属性,则会看到它为null。

java -Dlevel=1 A

[当您尝试将null传递到addToLevel(int x)并尝试将null自动拆箱为int x时会得到NPE。

此外,如果该类被多个线程使用,则应考虑在可重入的AtomicInteger类内部使用Singleton


2
投票

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

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


1
投票

[static Singleton instance = new Singleton();应该是最终版本,以防止出现竞争状况。

© www.soinside.com 2019 - 2024. All rights reserved.