【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. 最后捕获异常,进行异常处理

总结

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

相关推荐
V+zmm101343 分钟前
“返家乡”高校暑期社会实践微信小程序设计与开发ssm+论文源码调试讲解
java·小程序·毕业设计·mvc·ssm
earthzhang202110 分钟前
《深入浅出HTTPS》读书笔记(19):密钥
开发语言·网络协议·算法·https·1024程序员节
Cooloooo14 分钟前
Treap树堆【东北大学oj数据结构8-4】C++
开发语言·数据结构·c++
精神阿祝19 分钟前
使用Spring Boot、VUE实现SSE长连接:跟踪文件上传和任务进度
java·spring boot·后端·vue
CN.LG19 分钟前
浅谈Java注解之CachePut
java·开发语言·spring
_loehuang_20 分钟前
Spring MVC 请求头中 ContentType和DataType区别
java·spring·mvc
游侠小马哥21 分钟前
SpringBoot feign基于HttpStatus重试
java·spring boot
深情废杨杨22 分钟前
后端-添加购物车和查看购物车
java·spring boot·mysql
棐木25 分钟前
快速上手Spring注解、SpringAop
java·后端·spring
weisian15134 分钟前
Redis篇-19--运维篇1-主从复制(主从复制,读写分离,配置实现,实战案例)
java·运维·redis