【Java从入门到放弃 之 应用反射实现简单的序列化与反序列化】

应用反射实现简单的序列化与反序列化

应用反射实现简单的序列化与反序列化

反射技术,之前我已经写过一篇文章详细介绍了一下。不了解反射相关概念的同学可以阅读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);
        }
    }

我们通过使用反射技术,把相关数据拼接成具有特定格式的字符串。

方法实现步骤:

  1. 获取对象的类,Class<?> cls = obj.getClass();
  2. 创建 StringBuilder 对象,追加类名
  3. 遍历字段
  4. 异常处理

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);
    }
}

反序列化实际上就是,按照我们之前序列化定下的规则,反过来建立一个对象的过程。

方法实现步骤:

  1. 分割字符串,String[] strs = str.split("#");
  2. 检查类名是否存在,如果分割后的数组长度小于1,表示输入字符串不包含类名,抛出异常
  3. 加载类,Class<?> cls = Class.forName(strs[0]);
  4. 创建类的实例
  5. 处理字段值对
  6. 最后捕获异常,进行异常处理

总结

上面,我们写了一个简单的序列化与反序列化的案例,让我们体会到反射技术的强大。很明显,通过使用反射,我们的代码会具有更大的灵活性。但是需要注意的是,上面这个简答的序列化与反序列化只是一个让我们体会反射技术的案例,实际上要实现一个序列化与反序列化的通用方法要考虑很多安全性,性能与兼容性的处理。

相关推荐
Funcy6 分钟前
XxlJob 源码分析05:执行器注册流程
java
Boop_wu8 分钟前
[数据结构] 队列 (Queue)
java·jvm·算法
无敌的神原秋人11 分钟前
关于Redis不同序列化压缩性能的对比
java·redis·缓存
HMBBLOVEPDX30 分钟前
C++(静态函数)
开发语言·c++
Chan161 小时前
JVM从入门到实战:从字节码组成、类生命周期到双亲委派及打破双亲委派机制
java·jvm·spring boot·后端·intellij-idea
张晓~183399481211 小时前
短视频矩阵源码-视频剪辑+AI智能体开发接入技术分享
c语言·c++·人工智能·矩阵·c#·php·音视频
dpxiaolong1 小时前
RK3588 Android12默认移除导航栏
开发语言·python
招风的黑耳1 小时前
Java生态圈核心组件深度解析:Spring技术栈与分布式系统实战
java·spring·wpf
zhangyifang_0091 小时前
泛型通配符 T、E、K、V、?
java