频道栏目
首页 > 程序开发 > 综合编程 > 其他综合 > 正文
用私有构造器或者枚举类型强化Singleton - KuroNJQ - 博客园
2019-05-09 14:37:16         来源:KuroNJQ  
收藏   我要投稿

用私有构造器或者枚举类型强化Singleton

参考Effective Java第三版Joshua J. Bloch

参与编写JDK的大佬,上次看Collections的源码时看见了他的名字,然后翻了翻书,竟然就是他写的!

1.常见的一种:

public class Singleton {

通过反射:可以看到singleton的两个实例不是同一个。

class Main {
clazz = Singleton.class; try { Constructor constructor = clazz.getDeclaredConstructor(new Class[]{}); constructor.setAccessible(true); Singleton s2 = constructor.newInstance(new Class[]{}); System.out.println(s1 == s2); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }

2.用枚举:推荐的方法

优点:引用Effective Java的话:简洁,无偿的提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。单元素的枚举类常是实现Singleton的最佳方法。如果Singleton必须扩展一个超类,而不是扩展Enum时,不适宜使用这个方法。

public enum EnumSingleton {

按照第一个测试的时候会报错的。

3.序列化

序列化有个问题就是,反序列化时会创建一个新的实例,破坏单例,下面让原来那个类实现Serializable接口。

public class Singleton implements Serializable {

    private static final Singleton INSTANCE=new Singleton();

    private Singleton(){
        if (INSTANCE!=null){
            try {
                throw new Exception("INSTANCE已存在!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static Singleton getInstance(){
        return INSTANCE;
    }

    public void doSomething(){
        //...
    }
}

测试一下:Effective Java的第9条 使用try-with-resources优于try-finally,关闭资源的时候。

private static void testSerializableSingleton() {

打印的结果是false,说明序列化破化了单例,因为反序列化是反射调用了无参构造函数。

解决方法:在类里加入这个方法,详见Effective Java第89条

private Object readResolve() {
        return INSTANCE;
}

然后结果就是true了。

点击复制链接 与好友分享!回本站首页
相关TAG标签 - - 博客园
上一篇:一文搞懂HTTP协议及相关常见面试题 - 方块人 - 博客园
下一篇:设计模式学习方法 - 慧☆星 - 博客园
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站