为了账号安全,请及时绑定邮箱和手机立即绑定

在Java中实现单例模式的有效方法是什么?

在Java中实现单例模式的有效方法是什么?

元芳怎么了 2019-05-22 15:22:09
在Java中实现单例模式的有效方法是什么?在Java中实现单例模式的有效方法是什么?
查看完整描述

5 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

根据用途,有几个“正确”的答案。

从java5开始,最好的方法是使用枚举:

public enum Foo {
   INSTANCE;}

前java5,最简单的情况是:

public final class Foo {

    private static final Foo INSTANCE = new Foo();

    private Foo() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return INSTANCE;
    }

    public Object clone() throws CloneNotSupportedException{
        throw new CloneNotSupportedException("Cannot clone instance of this class");
    }}

我们来看看代码吧。首先,你希望课程是最终的。在这种情况下,我使用了final关键字让用户知道它是最终的。然后,您需要将构造函数设置为私有,以防止用户创建自己的Foo。从构造函数中抛出异常会阻止用户使用反射来创建第二个Foo。然后创建一个private static final Foo字段来保存唯一的实例,并创建一个public static Foo getInstance()返回它的方法。Java规范确保仅在首次使用类时调用构造函数。

当你有一个非常大的对象或繁重的构造代码并且还有其他可访问的静态方法或字段可能在需要实例之前使用时,那么你只需要使用延迟初始化。

您可以使用a private static class来加载实例。然后代码看起来像:

public final class Foo {

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }}

由于该行private static final Foo INSTANCE = new Foo();仅在实际使用类FooLoader时执行,因此它负责延迟实例化,并且保证是线程安全的。

当您还希望能够序列化对象时,需要确保反序列化不会创建副本。

public final class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }

    @SuppressWarnings("unused")
    private Foo readResolve() {
        return FooLoader.INSTANCE;
    }}

该方法readResolve()将确保将返回唯一的实例,即使该对象在上一次运行的程序中被序列化也是如此。


查看完整回答
反对 回复 2019-05-22
  • 5 回答
  • 0 关注
  • 812 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号