Effective Java -- 用私有构造器或者枚举类型强化Singleton属性

来源:互联网 发布:淘宝运营实训课教案 编辑:程序博客网 时间:2024/06/06 05:25

本文是 《Effective Java》第三条的读书笔记,由于是Java进阶书,难免会有理解的偏差,如有错误,非常欢迎能批评指正,本人不胜感激!


首先介绍两种常见的实现Singleton的方法

在这两个方法中,都需要把构造函数设置为私有private的,并导出该类的公有静态成员。

第一种方法中,公有静态成员是该类的实例(并且是final的),如下

class UserInfo{    public static final UserInfo userInfo = new UserInfo();    private UserInfo(){        // 用户通过反射机制再次创建实例,则抛异常(先不用理解,后面有说到)        if(UserInfo.userInfo!=null){            throw new RuntimeException("不能创建多个对象");        }    }}

这样在客户端直接通过如下代码即可获取实例(单例的)

UserInfo userInfo=UserInfo.userInfo;

第二种方法中,公有的成员是静态工厂方法,该方法返回该类的静态的final的实例,如下

class UserInfo{    private static final UserInfo userInfo = new UserInfo();    private UserInfo(){        // 用户通过反射机制再次创建实例,则抛异常(先不用理解,后面有说到)        if(UserInfo.userInfo!=null){            throw new RuntimeException("不能创建多个对象");        }    }    public static UserInfo getInstance(){        return UserInfo.userInfo;    }}

客户端的代码如下

UserInfo userInfo=UserInfo.getInstance();

但是上面的两个方法都会存在一个问题,如果我们通过Java的反射机制调用私有构造器则就会生成两个实例了

如果该构造函数被调用超过一次,我们可以在该对象的构造函数中抛出异常,如上面构造函数中的代码

        if(UserInfo.userInfo!=null){            throw new RuntimeException("不能创建多个对象");        }

我们利用Java反射机制来测试一下

package com.blog.effective3;import java.lang.reflect.Constructor;/** * @func 用私有构造器或者枚举类型强化Singleton属性. * @author 张俊强~ * @time 2017/10/30 21:00 */public class EffectiveJavaDemoOne {    public static void main(String[] args) throws Exception{        UserInfo userInfo=UserInfo.userInfo;        System.out.println(userInfo);        // 第利用反射机制调用私有构造函数        Class<?> class1 = Class.forName("com.blog.effective3.UserInfo");        // 得到构造函数        Constructor con = class1.getDeclaredConstructor();        con.setAccessible(true);        UserInfo userInfo1=(UserInfo) con.newInstance();//再次创建一个实例    }}class UserInfo{    public static final UserInfo userInfo = new UserInfo();    private UserInfo(){        // 用户通过反射机制再次创建实例,则抛异常        if(UserInfo.userInfo!=null){            throw new RuntimeException("不能创建多个对象");        }    }}

代码抛出如下异常

Caused by: java.lang.RuntimeException: 不能创建多个对象    at com.blog.effective3.UserInfo.<init>(EffectiveJavaDemoOne.java:33)    ... 10 more

实现Singleton的第三种方法这时候就登场了
其表现形式更加的简洁,无偿的提供了序列化机制,绝对的防止了多次实例化。
这种方式就是:单元素的枚举类型——实现Singleton的最佳方法。

enum StudentInfo{    STUDENT_INFO;}

客户端的代码如下

StudentInfo studentInfo=StudentInfo.STUDENT_INFO;

有关该章节中提到的序列化部分,本人了解不是非常的深入,故//TODO 以后再完善相关部分。

参考资料
[1].用私有构造器或者枚举类型强化Singleton属性


2017/10/30 21:58 于福州大学.

阅读全文
1 0
原创粉丝点击