要实现序列化代价是非常低的,低到什么程度呢?任何类只需要实现 Serializable
这个接口就是了,并且这个接口还是一个空接口,没有定义任何方法。但真的就这么简单吗?
定义一个 User 类,包含两个字段:一个 String 类型的 name,一个 int 类型的 age 。
User user = new User("zhangsan", 10);
System.out.println("序列化之前:" + user.toString());
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.obj"));
out.writeObject(user);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.obj"));
User u = (User) in.readObject();
in.close();
System.out.println("反序列化:" + u.toString());
运行结果如图。
我们就这样完成了一个简单的序列化和反序列化的过程,是不是觉得超级简单呢?
但现在用户都比较注重隐私,不想让别人知道年龄,不想序列化 age 字段,那应该怎么办呢?关键字 transient 出场了,使用关键字 transient 修饰不想序列化的字段就可以了,这里是修饰 age 。运行结果如图。
是不是觉得这样就完?NO!!!这只是一个开始。既然我们可以指定了某些字段的是否序列化,那么我们是不是同样自定义序列化规则呢?
但是应该怎么自定义序列化规则呢?Serializable
接口是没有任何方法。那么我们就看这个接口说明吧,如图。
通俗讲,我们想要自定义序列化规则,就是实现指定的方法。
private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
ObjectOutputStream.PutField putField = stream.putFields();
putField.put("name", name);
putField.put("age", age);
stream.writeFields();
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField getField = stream.readFields();
name = (String) getField.get("name", null);
age = (Integer) getField.get("age", 0);
}
运行结果如图。
可以达到和刚才一样的效果。
当然序列化还有一个最重要的东西。
private static final long serialVersionUID = 1024L;
这个最好自己声明,数字大小在合理范围内即可,如果不手动声明,这个会在序列化的时候随机生成,如果序列化和反序列胡的这个 id 不一致,会导致反序列化失败。验证方式也很简单,先序列化,然后修改 id ,接着反序列化。
序列化和反序列化还有很多的坑要踩,作者水平有限,就不展开讲解了。
PS:我其实准备了很多事例,但是那些代码报错千百怪,我自己都不能很好的解决,所以就放弃了。有兴趣的可以自己去网上搜索更多的教程。
欢迎大家关注我的微信公众号:卡戎