应用反射实现简单的序列化与反序列化
应用反射实现简单的序列化与反序列化
反射技术,之前我已经写过一篇文章详细介绍了一下。不了解反射相关概念的同学可以阅读Java反射。
序列化(Serialization)与反序列化(Deserialization)是 Java 编程中非常重要的概念,尤其是在分布式系统、网络通信和持久化存储等场景下。它们用于将对象转换为一种格式,以便可以轻松地保存到文件或通过网络传输,并且可以在稍后的时间点恢复回原始对象。
实现
java
public class Test31 {
public static void main(String[] args) {
Cat cat = new Cat(1, "bill");
String s = SerializationUtils.toString(cat);
System.out.println(s);
Cat cat1 = (Cat) SerializationUtils.fromString(s);
System.out.println(SerializationUtils.toString(cat1));
}
}
class Cat{
private int age;
private String name;
public Cat() {
}
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我们新建SerializationUtils类实现我们序列化与反序列化,SerializationUtils.toString()用来把一个对象序列化成一个字符串; SerializationUtils.fromString()用来把一个字符串反序列化成一个对象。
SerializationUtils.toString()序列化方法
java
public static String toString(Object obj) {
try {
Class<? > cls = obj.getClass();
StringBuilder sb = new StringBuilder();
sb.append(cls.getName() + "#");
for(Field f : cls.getDeclaredFields()) {
f.setAccessible(true);
sb.append(f.getName() + "=" + f.get(obj).toString() + "#");
}
return sb.toString();
} catch(IllegalAccessException e) {
throw new RuntimeException(e);
}
}
我们通过使用反射技术,把相关数据拼接成具有特定格式的字符串。
方法实现步骤:
- 获取对象的类,Class<?> cls = obj.getClass();
- 创建 StringBuilder 对象,追加类名
- 遍历字段
- 异常处理
SerializationUtils.fromString() 反序列化
java
public static Object fromString(String str) {
try {
String[] strs = str.split("#");
if(strs.length < 1) {
throw new Exception(str);
}
Class<? > cls = Class.forName(strs[0]);
Object obj = cls.newInstance();
if(strs.length > 1) {
for(int i = 1; i < strs.length; i++) {
String[] fv = strs[i].split("=");
if(fv.length != 2) {
throw new IllegalArgumentException(strs[i]);
}
Field f = cls.getDeclaredField(fv[0]);
f.setAccessible(true);
setFieldValue(f, obj, fv[1]);
}
}
return obj;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
java
private static void setFieldValue(Field field, Object obj, String value) throws IllegalAccessException {
Class<?> fieldType = field.getType();
if (fieldType == int.class || fieldType == Integer.class) {
field.setInt(obj, Integer.parseInt(value));
} else if (fieldType == double.class || fieldType == Double.class) {
field.setDouble(obj, Double.parseDouble(value));
} else if (fieldType == boolean.class || fieldType == Boolean.class) {
field.setBoolean(obj, Boolean.parseBoolean(value));
} else if (fieldType == String.class) {
field.set(obj, value);
} else {
throw new IllegalArgumentException("Unsupported field type: " + fieldType);
}
}
反序列化实际上就是,按照我们之前序列化定下的规则,反过来建立一个对象的过程。
方法实现步骤:
- 分割字符串,String[] strs = str.split("#");
- 检查类名是否存在,如果分割后的数组长度小于1,表示输入字符串不包含类名,抛出异常
- 加载类,Class<?> cls = Class.forName(strs[0]);
- 创建类的实例
- 处理字段值对
- 最后捕获异常,进行异常处理
总结
上面,我们写了一个简单的序列化与反序列化的案例,让我们体会到反射技术的强大。很明显,通过使用反射,我们的代码会具有更大的灵活性。但是需要注意的是,上面这个简答的序列化与反序列化只是一个让我们体会反射技术的案例,实际上要实现一个序列化与反序列化的通用方法要考虑很多安全性,性能与兼容性的处理。