一、背景
《阿里巴巴 Java开发手册》详解专栏 的第 3节,主要讲解了序列化的概念,序列化的主要实现方式,以及序列化和反序列化的一些坑点。
并给出了一个课后题:
给出一个PersonTransit
类,一个Address
类,假设Address
是其他 jar 包中的类,没实现序列化接口。请使用今天讲述的自定义的函数writeObject
和readObject
函数实现PersonTransit
对象的序列化,要求反序列化后address
的值正常。
@Data public class PersonTransit implements Serializable { private Long id; private String name; private Boolean male; private List<PersonTransit> friends; private transient Address address; } @Data @AllArgsConstructor public class Address { private String detail; }
序列化主要有两个困难:
1 transient 关键字,序列化时默认不序列化该字段。(新加的,增加难度)
2 假设 Address 是第三方 jar 包中的类,不允许修改实现序列化接口。
二、分析
我们通过专栏的介绍还有序列化接口java.io.Serializable的注释可知,可以自定义序列化方法和反序列化方法:
private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
实现序列化和反序列化不可序列化的属性,也可以对序列化的数据进行数据的加密和解密处理。
三、参考代码
@Data public class PersonTransit implements Serializable { private Long id; private String name; private Boolean male; private List<PersonTransit> friends; private transient Address address; /** * 自定义序列化写方法 */ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(address.getDetail()); } /** * 自定义反序列化读方法 */ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); this.setAddress(new Address( (String) ois.readObject())); } }
单元测试
@Test public void testJDKSerialOverwrite() throws IOException, ClassNotFoundException { PersonTransit person = new PersonTransit(); person.setId(1L); person.setName("张三"); person.setMale(true); person.setFriends(new ArrayList<>()); Address address = new Address(); address.setDetail("某某小区xxx栋yy号"); person.setAddress(address); // 序列化 JdkSerialUtil.writeObject(file, person); // 反序列化 PersonTransit personTransit = JdkSerialUtil.readObject(file); // 判断是否相等 Assert.assertEquals(personTransit.getName(), person.getName()); Assert.assertEquals(personTransit.getAddress().getDetail(), person.getAddress().getDetail()); }
用到的工具类:
public class JdkSerialUtil { public static <T> void writeObject(File file, T data) throws IOException { try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));) { objectOutputStream.writeObject(data); objectOutputStream.flush(); } } public static <T> void writeObject(ByteArrayOutputStream outputStream, T data) throws IOException { try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);) { objectOutputStream.writeObject(data); objectOutputStream.flush(); } } public static <T> T readObject(File file) throws IOException, ClassNotFoundException { FileInputStream fin = new FileInputStream(file); ObjectInputStream objectInputStream = new ObjectInputStream(fin); return (T) objectInputStream.readObject(); } public static <T> T readObject(ByteArrayInputStream inputStream) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); return (T) objectInputStream.readObject(); } }
通过单元测试验证了我们编写代码的正确性。
四、总结
大家学习知识时要敢于尝试,写不出来说明理解不够到位,找一些例子去参考,只有自己能自主改编才能说明真正会运用。
只有基础扎实,学的更多,才更容易找到问题的解决方法。
学习时要多看源码和源码的注释,这样可以学到更多。
想了解更多《手册》详解的更多内容,想学习更多开发和避坑技巧,少走弯路,请关注《阿里巴巴Java 开发手册》详解专栏。
大家购买前有啥疑问或者想和其他读者交流可以用base64算法解密以下内容: 5re75Yqg5b6u5L+hICBmZW5neWVsaWFvemhhaSAg5bm255WZ6KiA77ya5Yqg5YWl44CK5omL5YaM44CL6K+m6Kej5LiT5qCP6K+76ICF5Lqk5rWB576k44CC
热门评论
不错, 学习了