在Java中实现单例模式的有效方法是什么?推荐| Java Debug 笔记

417 阅读2分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看活动链接

Java中的守护程序线程是什么?

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

高分回答:

很多的知识点,真的需要写出来才会掌握!!! \color{purple}很多的知识点,真的需要写出来才会掌握!!!{~}

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

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

public enum Foo {
   INSTANCE;
}

Java 5之前的版本,最简单的情况是:

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规范确保仅在首次使用该类时才调用构造函数。

如果您有一个很大的对象或繁重的构造代码,并且在需要实例之前又有其他可访问的静态方法或字段可以使用,则仅在那时才需要使用惰性初始化。

您可以使用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()将确保将返回唯一的实例,即使该对象在程序的先前运行中已被序列化也是如此。

文章翻译自 am2dgbqfb6mk75jcyanzabc67y-ac4c6men2g7xr2a-stackoverflow-com.translate.goog/questions/7…

作者建议: 静态内部类我知道,在属性较少时使用枚举也可以,哈哈,学到了

欢迎关注我的专栏StackOverFlow,我会筛选优质的问答,面试常考!!! \color{red}欢迎关注我的专栏StackOverFlow,我会筛选优质的问答,面试常考!!!{~}

有最新、优雅的实现方式,我也会在文末写出我对本问答的见解 \color{red}有最新、优雅的实现方式,我也会在文末写出我对本问答的见解{~}

真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话

求点赞👍 求关注❤️ 求分享👥 对8块腹肌的我来说真的 非常有用!!!

如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️