本文是 《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.(EffectiveJavaDemoOne.java:33)
... 10 more
实现Singleton
的第三种方法这时候就登场了
其表现形式更加的简洁,无偿的提供了序列化机制,绝对的防止了多次实例化。
这种方式就是:单元素的枚举类型——实现Singleton的最佳方法。
enum StudentInfo{
STUDENT_INFO;
}
客户端的代码如下
StudentInfo studentInfo=StudentInfo.STUDENT_INFO;
有关该章节中提到的序列化部分,本人了解不是非常的深入,故//TODO 以后再完善相关部分。
参考资料
[1].用私有构造器或者枚举类型强化Singleton属性
2017/10/30 21:58 于福州大学.