栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之饿汉单例实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之饿汉单例实现

设计模式之单例实现

单例模式------即在内存中只存在该对象得一个实例

    饿汉方式------即创建实例对象的时机是在类加载时:只要使用到该类就会触发private static Test Instance=new Test();此句代码运行,调用构造方法创建一个实例对象。且饿汉式没有多线程安全问题,都是以jvm保证安全的。

1.简单方式实现饿汉


public class Test implements Serializable {

    //静态实例代码段,饿汉实现类加载初始化时调用构造方法
    private static Test Instance=new Test();

    //私有方法防止外部调用创建对象
    private Test(){
        System.out.println("构造方法");
    }

    //外部类获得单例对象方法
    public static Test getInstance(){
        return Instance;
    }
    //其他方法
    public static void otherMethod(){
        System.out.println("other");
    }
}

该单例实现方式可以被反序列化和反射破坏,反射破坏方式如下:该方式可以通过构造方法创建出一个全新的实例对象

public static void reflect() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        System.out.println(Test.getInstance());
        //反射破坏
        //得到类
        Class c = Test.class;
        Constructor constructor = c.getDeclaredConstructor();
        //设置私有可调用
        constructor.setAccessible(true);
        // 打印创建的实例对象
        System.out.println(constructor.newInstance());

    }


可见该方法是通过调用构造方法创建出一个新的对象

反序列化破坏单例方式如下:

public static void ser() throws IOException, ClassNotFoundException {
        //反序列化
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
        //将类转化
        objectOutputStream.writeObject(Test.getInstance());
        System.out.println(Test.getInstance());
        ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
        //读出类,变为一个新的类
        Test test= (Test) objectInputStream.readObject();
        System.out.println(test);
    }


该方式可以看出反序列化构造出的对象并不是通过构造方法!

由此针对上面两种破坏方式做出优化得到以下的代码

public class Test implements Serializable {

    //静态实例代码段,饿汉实现类加载初始化时调用构造方法
    private static Test Instance=new Test();

    //私有方法防止外部调用创建对象
    private Test(){
        if(Instance!=null)// 此处方式反射调用破环单例对象,抛出异常
            throw new RuntimeException("单例模式不能创建");
        System.out.println("构造方法");
    }

    //外部类获得单例对象方法
    public static Test getInstance(){
        return Instance;
    }
    //其他方法
    public static void otherMethod(){
        System.out.println("other");
    }

    //防止反序列化破坏单例
    public Object readResolve(){
        return  Instance;
    }
}

2.枚举类实现饿汉

public enum  Test_1 {

    
    Instance;
    //枚举类默认构造方法私有
    Test_1(){
        System.out.println("构造方法");
    }
    //获取对象
    public static Test_1 getInstance(){
        return Instance;
    }

    //其他方法
    public static void otherMethod(){
        System.out.println("other");
    }
}

枚举类实现方式不会被反射和反序列化破环单例

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/733189.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号