手写序列化和反序列化类
本文通过实现一个序列化和反序列化的工具类,进一步加强对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再解析成对象,这就是反序列化的过程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗