【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(strs0);
  4. 创建类的实例
  5. 处理字段值对
  6. 最后捕获异常,进行异常处理

总结

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

相关推荐
Chester_19992 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
EXI-小洲3 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员4 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导4 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan4 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt
m0_695251494 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)
开发语言·qt
2601_961901704 小时前
SpringBoot使用Nacos进行application.yml配置管理
java·spring boot·spring
何以解忧,唯有..5 小时前
LangChain 工具调用(Tool Calling)实战指南
java·前端·langchain
大衛說5 小时前
《Python 从入门到精通》系列总览与学习路线
开发语言·python·学习
QQ_21696290966 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端