手写序列化和反序列化类

本文通过实现一个序列化和反序列化的工具类,进一步加强对java高级特性中的反射理解。

实现效果

通过构造函数实例化Person类。通过PersonCast类toString方法进行反序列化,输出文本;通过toObject方法重新实例化Person对象。

输出结果

实现思路

  • 序列化对象
    Ⅰ. 获取对象的Class对象
    Ⅱ. 使用Class对象,获取对象的类名,字段名称
    Ⅲ. 使用Field对象获取属性值
    Ⅳ. 整理文本格式,输出文本

  • 反序列化对象
    Ⅰ. 根据文本获取反序列化对象的Class对象,进行初始化
    Ⅱ. 使用Class对象实例化对象
    Ⅲ. 解析文本中的对象属性名和属性内容,使用Field对象进行赋值
    Ⅳ. 返回对象

实现代码

public class PersonCast {
    private Person person;

    public PersonCast(Person person) {
        this.person = person;
    }


    @Override
    public String toString() {
        StringBuilder personString = new StringBuilder();
        List<String> stringList = new ArrayList<>();
        Class<?> cls = this.person.getClass();

        //获取对象类名称
        personString.append(cls.getName());
        //获取字段属名称
        Field[] fields = cls.getDeclaredFields();
        personString.append("{");
        //遍历获取字段属性内容
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                String elm = f.getName() + "=" + f.get(this.person);
                stringList.add(elm);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        personString.append(String.join(",", stringList));
        personString.append("}");
        return personString.toString();
    }


    public Object toObject(String objectString) {
        //获取类名
        String className = objectString.substring(0, objectString.indexOf("{"));
        //获取属性名称和内容
        String[] fieldArr = objectString.substring(objectString.indexOf("{")+1, objectString.lastIndexOf("}")).split(",");

        try {
            //初始化对象
            Class<?> cls = Class.forName(className);
            //实例化对象
            Object obj = cls.newInstance();//其实也可以用对象属性进行实例化
            //填充对象属性
            for (String s : fieldArr) {
                String fieldContext[] = s.split("=");
                String fieldName = fieldContext[0];
                String fieldValue = fieldContext[1];
                Field field = cls.getDeclaredField(fieldName);
                field.setAccessible(true);
                setFieldValue(field,obj,fieldValue);
            }
            return obj;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void setFieldValue(Field field, Object obj, String value) {
        Class<?> type = field.getType();
        try {
            if (type == int.class) {
                field.setInt(obj, Integer.parseInt(value));
            } else if (type == byte.class) {
                field.setByte(obj, Byte.parseByte(value));
            } else if (type == short.class) {
                field.setShort(obj, Short.parseShort(value));
            } else if (type == long.class) {
                field.setLong(obj, Long.parseLong(value));
            } else if (type == float.class) {
                field.setFloat(obj, Float.parseFloat(value));
            } else if (type == double.class) {
                field.setDouble(obj, Double.parseDouble(value));
            } else if (type == char.class) {
                field.setChar(obj, value.charAt(0));
            } else if (type == boolean.class) {
                field.setBoolean(obj, Boolean.parseBoolean(value));
            } else if (type == String.class) {
                field.set(obj, value);
            } else {
                //假设有一个String类型的构造方法
                Constructor<?> ctor = type.getConstructor(
                        new Class[]{String.class});
                field.set(obj, ctor.newInstance(value));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
public class Person {
    private String name;
    private Integer age;
    private Double birth;

    public Person() {
    }

    public Person(String name, Integer age, Double birth) {
        this.name = name;
        this.age = age;
        this.birth = birth;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Double getBirth() {
        return birth;
    }

    public void setBirth(Double birth) {
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birth=" + birth +
                '}';
    }
}

在反射中,入口为Class类。获取Class类对象有三种方式

  • 直接使用 类名.class
  • 使用实例对象.getClass()
  • class.forName(类名)

再根据Class获取field,method,consrtuctor等属性对象,进行初始化对象,访问修改成员,修改方法等。

小结

做到最后突然想到springmvc有一个类似的应用场景,在Controller类中直接返回的Dto对象,在接口就是以json的形式输出,是序列化对象属性的过程;
当使用form表单提交json数据时,springmvc将json再解析成对象,这就是反序列化的过程。

posted @   dxyoung  阅读(456)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示