目录
一、Enum枚举单例
- 一、Enum枚举单例
- 二、序列化和反序列化枚举单例,查看是否是同一实例
- 三、序列化和反序列化枚举单例,查看是否是同一对象
- 四、通过反射机制获取枚举单例对象,查看是否能获取
1、 定义一个枚举类
package com.rf.designPatterns.singleton.enumSingleton;
/**
* @description: 定义一个枚举类
* @author: xiaozhi
* @create: 2020-06-01 20:50
* 枚举类的单例模式
* 1、序列化和反序列化不会出现多次实例化的情况
* 2、对于反射攻击也不会存在问题
* 3、EffecttiveJava书中强烈推荐枚举类单例模式
*/
public enum EnumInstance {
//声明一个变量
INSTANCE;
//声明一个Object类型的成员变量
private Object data;
//setter、getter方法
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//对外暴露的方法。
public static EnumInstance getInstance(){
return INSTANCE;
}
}
二、序列化和反序列化枚举单例,查看是否是同一实例
1、定义一个枚举类
package com.rf.designPatterns.singleton.enumSingleton;
/**
* @description: 定义一个枚举类
* @author: xiaozhi
* @create: 2020-06-01 20:50
* 枚举类的单例模式
* 1、序列化和反序列化不会出现多次实例化的情况
* 2、对于反射攻击也不会存在问题
* 3、EffecttiveJava书中强烈推荐枚举类单例模式
*/
public enum EnumInstance {
//声明一个变量
INSTANCE;
//声明一个Object类型的成员变量
private Object data;
//setter、getter方法
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//对外暴露的方法。
public static EnumInstance getInstance(){
return INSTANCE;
}
}
2、定义一个序列化和反序列化枚举单例的测试类
package com.rf.designPatterns.singleton.enumSingleton;
import java.io.*;
/**
* @description: 序列化和反序列化测试类
* @author: xiaozhi
* @create: 2020-06-01 21:01
*/
public class Test1 {
public static void main(String[] args) {
//序列化
EnumInstance enumInstance = EnumInstance.getInstance();
ObjectOutputStream oos=null;
try {
oos = new ObjectOutputStream(new FileOutputStream("singlton_file"));
oos.writeObject(enumInstance);
} catch (IOException e) {
e.printStackTrace();
}
//反序列化
File file = new File("singlton_file");
EnumInstance newEnumInstance=null;
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
newEnumInstance= (EnumInstance) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("序列化之前的对象:"+enumInstance);
System.out.println("反序列化后的对象:"+newEnumInstance);
System.out.println(enumInstance==newEnumInstance);
}
}
3、输出结果如下:
结论:序列化和反序列化不会出现多次实例化的情况
三、序列化和反序列化枚举单例,查看是否是同一对象1、定义一个枚举类
package com.rf.designPatterns.singleton.enumSingleton;
/**
* @description: 定义一个枚举类
* @author: xiaozhi
* @create: 2020-06-01 20:50
* 枚举类的单例模式
* 1、序列化和反序列化不会出现多次实例化的情况
* 2、对于反射攻击也不会存在问题
* 3、EffecttiveJava书中强烈推荐枚举类单例模式
*/
public enum EnumInstance {
//声明一个变量
INSTANCE;
//声明一个Object类型的成员变量
private Object data;
//setter、getter方法
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//对外暴露的方法。
public static EnumInstance getInstance(){
return INSTANCE;
}
}
2、定义一个序列化和反序列化枚举单例的测试类,并且获取实例的时候set一个对象。
package com.rf.designPatterns.singleton.enumSingleton;
import java.io.*;
/**
* @description: 序列化和反序列化测试类
* @author: xiaozhi
* @create: 2020-06-01 21:01
*/
public class Test1 {
public static void main(String[] args) {
//序列化
EnumInstance enumInstance = EnumInstance.getInstance();
enumInstance.setData(new Object());
ObjectOutputStream oos=null;
try {
oos = new ObjectOutputStream(new FileOutputStream("singlton_file"));
oos.writeObject(enumInstance);
} catch (IOException e) {
e.printStackTrace();
}
//反序列化
File file = new File("singlton_file");
EnumInstance newEnumInstance=null;
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
newEnumInstance= (EnumInstance) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("序列化之前的对象:"+enumInstance.getData());
System.out.println("反序列化后的对象:"+newEnumInstance.getData());
System.out.println(enumInstance.getData()==newEnumInstance.getData());
}
}
3、输出结果如下:
结论:序列化和反序列化也不会出现创建不同对象的情况
四、通过反射机制获取枚举单例对象,查看是否能获取1、定义一个枚举单例类
package com.rf.designPatterns.singleton.enumSingleton;
/**
* @description: 定义一个枚举类
* @author: xiaozhi
* @create: 2020-06-01 20:50
* 枚举类的单例模式
* 1、序列化和反序列化不会出现多次实例化的情况
* 2、对于反射攻击也不会存在问题
* 3、EffecttiveJava书中强烈推荐枚举类单例模式
*/
public enum EnumInstance {
//声明一个变量
INSTANCE;
//声明一个Object类型的成员变量
private Object data;
//setter、getter方法
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//对外暴露的方法。
public static EnumInstance getInstance(){
return INSTANCE;
}
}
2、定义一个反射攻击获取枚举单例的实例测试类
package com.rf.designPatterns.singleton.enumSingleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @description: 定义一个反射攻击获取枚举单例的实例测试类
* @author: xiaozhi
* @create: 2020-06-02 22:03
*/
public class Test2 {
public static void main(String[] args) {
//反射攻击获取枚举单例的实例
Class enumInstanceClass = EnumInstance.class;
try {
Constructor declaredConstructor = enumInstanceClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
EnumInstance newEnumInstance = declaredConstructor.newInstance();
System.out.println(newEnumInstance);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
3、输出如下图:没有获取到无参构造器报错。
结论:对于反射攻击无法获取枚举单例实例,所以反射攻击失败。