Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有理由在Java中的另一个类中保留对单例实例的引用?_Java_Singleton - Fatal编程技术网

是否有理由在Java中的另一个类中保留对单例实例的引用?

是否有理由在Java中的另一个类中保留对单例实例的引用?,java,singleton,Java,Singleton,这可能是一个相当愚蠢的问题,但今天早些时候,我遇到了一些代码,其中外部类存储对单例类实例的引用(在私有字段中),并使用此引用,而不是每次都从单例类获取实例 起初,我觉得它的设计很糟糕,因为它在类中添加了一个字段,但有没有其他原因不应该这样做(或者应该这样做) 小代码示例来说明: enum SomeSingletonObject { INSTANCE; public void someMethod() {...} } class AnotherObject { priv

这可能是一个相当愚蠢的问题,但今天早些时候,我遇到了一些代码,其中外部类存储对单例类实例的引用(在私有字段中),并使用此引用,而不是每次都从单例类获取实例

起初,我觉得它的设计很糟糕,因为它在类中添加了一个字段,但有没有其他原因不应该这样做(或者应该这样做)

小代码示例来说明:

enum SomeSingletonObject {
    INSTANCE;

    public void someMethod() {...}
}

class AnotherObject {
    private SomeSingletonObject sso;

    public AnotherObject() {
        this.sso = SomeSingletonObject.INSTANCE;
    }

    public void someMethod() {
        sso.someMethod();
        // instead of 
        // SomeSingletonObject.INSTANCE.someMethod();
    }
}

在这个例子中,没有,没有好处


但是,如果您使用依赖项注入,而您的类将其依赖项作为构造函数参数,那么传入一个单例实例可能非常有用,在这种情况下,您将别无选择,只能存储引用。

实际上,我可以从中受益,因为如果您使用带有构造函数的枚举来管理静态引用,它将在启动时初始化(如在类加载时),并且在启动后永远不会更改

这可能有助于分离permgen类,这可能会改进容器的热部署,因为这是一个问题。但我不知道事实是否如此

消极的一面是,如果枚举正在进行初始化,您可能会失去静态引用的生命周期管理


更好的解决方案通常是避免像这样的静态单例,并依赖依赖依赖注入或AOP(Google Spring的@Configurable)。

如果您可以保证给定的单例确实是单例,那么这种方法将起作用。在更复杂的环境中,它可能会失败,例如:

public class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton instance() {

        if (someCondition == true) {
            Singleton.instance.close() // close the object
            Singleton.instance = new Singleton();
        }

        return Singleton.instance;
    }
}
上面的示例并不是一个真正的单例,但它会破坏您提供的代码,因为新的引用已分配给
实例
。如果使用外部库而不了解/访问它们的内部行为,则可能会出现这些问题


我会避免“缓存”对单例的引用。

想到的第一个原因是使它易于替换为其他对象,即实现公共接口或扩展公共超类的对象

此外,如果由不同的类装入器装入,则可能存在两个单例实例


此外,尽管不完全符合singleton模式的精神,但它可以用于存储对singleton对象的旧实例的引用。

+1表示DI引用。一直都是在春天做的。带有DAO服务的控制器,所有单例。但在这种情况下,单例将作为参数或通过setter传入。看看OP的完整场景会很有趣的。的确如此。通过一个人为的例子,很难给出一个明确的答案。这是一个非常广泛的问题,更多地取决于这些类的生命周期以及如何将单例注入到外部类中。