1. 概述
2. 代码解析
- 查看博主写的优雅单例模式。
3. 破坏单列模式
- 序列化和反序列化:
会得到不同的对象;反序列化的时候,是通过反射重新获取了一个新的实例。
public class HungerSingleton implements Serializable {
private final static HungerSingleton HUNGER_SINGLETON = new HungerSingleton();
private HungerSingleton() { }
public static HungerSingleton getInstance() {
return HUNGER_SINGLETON;
}
/**
* 使用这个方法, 来保证序列化之后, 不会获取反射得到的对象;
* 1. 读取Object: {@link ObjectInputStream#readObject();}
* 2. 判断读取的是什么类型的对象: {@link ObjectInputStream#readObject0}
* 3. {@link ObjectInputStream#readOrdinaryObject}: 通过反射生成对象, 检测对象类中是否包含'readResolve'方法;
* 若无此方法, 返回反射得到的对象; 否则, 返回对象类中的readResolve方法的返回值.
*/
public Object readResolve() {
return HUNGER_SINGLETON;
}
}
public class HungerSingletonTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
HungerSingleton hungerSingleton = HungerSingleton.getInstance();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hunger"));
oos.writeObject(hungerSingleton);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hunger"));
HungerSingleton newInstance = (HungerSingleton) ois.readObject();
System.out.println(hungerSingleton);
System.out.println(newInstance);
System.out.println(newInstance == hungerSingleton);
}
}
-
反射
- 反射可以获取到构造函数,因此,可以实例化对象。
- 防护:就是在私有构造方法中,验证是否已经存在实例化的对象,存在则抛出异常;
-
克隆
- 通过反射调用clone方法, 可以获得实例化对象。
- 防护:clone方法中调用
getIntance
方法,而不是clone一个新的对象处理。
4. 源码应用
- JDK中
RunnTime
类。