(2) 测试类
先进行序列化, 再进行反序列化。
public class SerializableTest { private static void serialize(User user) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:\\111.txt"))); oos.writeObject(user); oos.close(); } private static User deserialize() throws Exception{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:\\111.txt"))); return (User) ois.readObject(); } public static void main(String[] args) throws Exception { User user = new User(); user.setName("tyshawn"); user.setAge(18); System.out.println("序列化前的结果: " + user); serialize(user); User dUser = deserialize(); System.out.println("反序列化后的结果: "+ dUser); } }
(3) 结果
先注释掉反序列化代码, 执行序列化代码, 然后User类新增一个属性sex。
public class User implements Serializable { private String name; private Integer age; private String sex; 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } }
再注释掉序列化代码执行反序列化代码, 最后结果如下:
序列化前的结果: User{name='tyshawn', age=18}
Exception in thread "main" java.io.InvalidClassException: org.tyshawn.SerializeAndDeserialize.User; local class incompatible: stream classdesc serialVersionUID = 1035612825366363028, local class serialVersionUID = -1830850955895931978
报错结果为序列化与反序列化产生的serialVersionUID不一致。
接下来我们在上面User类的基础上显示指定一个serialVersionUID
private static final long serialVersionUID = 1L;
再执行上述步骤, 测试结果如下:
序列化前的结果: User{name='tyshawn', age=18}
反序列化后的结果: User{name='tyshawn', age=18, sex='null'}
显示指定serialVersionUID后就解决了序列化与反序列化产生的serialVersionUID不一致的问题。
Java序列化的其他特性
先说结论, 被transient关键字修饰的属性不会被序列化, static属性也不会被序列化。
我们来测试下这个结论:
(1) User类
public class User implements Serializable { private static final long serialVersionUID = 1L; private String name; private Integer age; private transient String sex; private static String signature = "你眼中的世界就是你自己的样子"; 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public static String getSignature() { return signature; } public static void setSignature(String signature) { User.signature = signature; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex +'\'' + ", signature='" + signature + '\'' + '}'; } }
(2) 测试类
public class SerializableTest { private static void serialize(User user) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:\\111.txt"))); oos.writeObject(user); oos.close(); } private static User deserialize() throws Exception{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:\\111.txt"))); return (User) ois.readObject(); } public static void main(String[] args) throws Exception { User user = new User(); user.setName("tyshawn"); user.setAge(18); user.setSex("man"); System.out.println("序列化前的结果: " + user); serialize(user); User dUser = deserialize(); System.out.println("反序列化后的结果: "+ dUser); } }
(3) 结果
先注释掉反序列化代码, 执行序列化代码, 然后修改User类signature = “我的眼里只有你”, 再注释掉序列化代码执行反序列化代码, 最后结果如下:
序列化前的结果: User{name='tyshawn', age=18, sex='man', signature='你眼中的世界就是你自己的样子'}
反序列化后的结果: User{name='tyshawn', age=18, sex='null', signature='我的眼里只有你'}
static属性为什么不会被序列化?
因为序列化是针对对象而言的, 而static属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化。
看到这个结论, 是不是有人会问, serialVersionUID也被static修饰, 为什么serialVersionUID会被序列化? 其实serialVersionUID属性并没有被序列化, JVM在序列化对象时会自动生成一个serialVersionUID, 然后将我们显示指定的serialVersionUID属性值赋给自动生成的serialVersionUID。