java中生成对象的方式有:
1、使用new关键关键字生成对象
2、clone生成对象
3、instance反射生成对象
4、序列化和反序列化生成生成对象。
下面针对上面的几种对象生成方式来防止单例被破解
序列化和反序列化
只需要在单例的实体类添加一个方法即可
package com.singleton;
import java.io.Serializable;
public class SingletonHungry implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private final static SingletonHungry singletonHungry = new SingletonHungry();
private SingletonHungry(){
if(singletonHungry!=null){
throw new RuntimeException();
}
}
public static SingletonHungry getSingletonHungry(){
return singletonHungry;
}
//在序列化时,会自动调用该方法
private Object readResolve(){
return singletonHungry;
}
}
Client
SingletonHungry s1 = SingletonHungry.getSingletonHungry();
System.out.println(s1);
FileOutputStream fileInputStream = new FileOutputStream("d:/2.txt");
ObjectOutputStream oos = new ObjectOutputStream(fileInputStream);
oos.writeObject(s1);
oos.close();
fileInputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("d:/2.txt"));
SingletonHungry readObject = (SingletonHungry) inputStream.readObject();
inputStream.close();
System.out.println(readObject);
反射:只需在构造方法中添加判断即可
//反射,防止出现再次反射生成新对象
private SingletonHungry(){
if(singletonHungry!=null){
throw new RuntimeException();
}
}
Client
Class<SingletonHungry> clazz = (Class<SingletonHungry>) Class.forName("com.singleton.SingletonHungry");
Constructor<SingletonHungry> declaredConstructor = clazz.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
SingletonHungry newInstance = declaredConstructor.newInstance();
SingletonHungry newInstance2 = declaredConstructor.newInstance();
System.out.println(newInstance);
System.out.println(newInstance2);