序列化 Serializable

Java序列化版本号解决更新异常问题
博客介绍了Java中类通过实现Serializable接口启用序列化功能,未实现该接口会抛出异常。还指出序列化完成后,企业推送升级程序时,若类未加序列化版本号,反序列化会出现异常,添加版本号可解决此问题,开发中需注意添加。

1.Serializable

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化,并抛出异常;

异常代码:

1 java.io.NotSerializableException: cn.a2.serializable.Student
2     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
3     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
4     at cn.a2.serializable.Test1.main(Test1.java:22)
 1 package cn.a2.serializable;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Student implements Serializable {
 6 
 7     private String id;
 8     private String name;
 9     private int age;
10     private Gender gender;
11     public String getId() {
12         return id;
13     }
14     public void setId(String id) {
15         this.id = id;
16     }
17     public String getName() {
18         return name;
19     }
20     public void setName(String name) {
21         this.name = name;
22     }
23     public int getAge() {
24         return age;
25     }
26     public void setAge(int age) {
27         this.age = age;
28     }
29     public Gender getGender() {
30         return gender;
31     }
32     public void setGender(Gender gender) {
33         this.gender = gender;
34     }
35     public Student(String id, String name, int age, Gender gender) {
36         super();
37         this.id = id;
38         this.name = name;
39         this.age = age;
40         this.gender = gender;
41     }
42     public Student() {
43         super();
44     }
45     
46     @Override
47     public String toString() {
48         return "Student [id=" + id + ", name=" + name + ", age=" + age
49                 + ", gender=" + gender + "]";
50     }
51     
52 
53 }
54 
55 enum Gender {
56     男, 女;
57 
58 }

把属性信息写入d:"+File.separator+"javatest"+File.separator+"e.txt文件里:

 1 package cn.a2.serializable;
 2 
 3 import java.io.File;
 4 import java.io.FileNotFoundException;
 5 import java.io.FileOutputStream;
 6 import java.io.IOException;
 7 import java.io.ObjectOutputStream;
 8 
 9 public class Test1 {
10     public static void main(String[] args) throws FileNotFoundException, IOException {
11         Student student = new Student("1001", "小明", 20, Gender.男);
12         
13         /*
14          *取stu所有属性,通过特定的字符串(-),把各个属性值连接起来 
15          * 1001-小明-20-男
16          */
17         
18         File file = new File("d:"+File.separator+"javatest"+File.separator+"e.txt");
19         FileOutputStream fos = new FileOutputStream(file);
20         ObjectOutputStream oos = new ObjectOutputStream(fos);
21         
22         oos.writeObject(student);
23         
24         oos.close();
25         fos.close();
26         
27         
28     }
29 
30 }

反序列化

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.IOException;
 5 import java.io.ObjectInputStream;
 6 
 7 public class Test2 {
 8     public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
 9         File file = new File("d:"+File.separator+"javatest"+File.separator+"e.txt");
10         
11         FileInputStream iStream = new FileInputStream(file);
12         ObjectInputStream ois = new ObjectInputStream(iStream);
13         
14         Student student = (Student)ois.readObject();
15         System.out.println(student.getId());
16         System.out.println(student.getName());
17         System.out.println(student.getAge());
18         System.out.println(student.getGender());
19         
20         iStream.close();
21         ois.close();
22     }
23 
24 }

此时可能会出现异常

注意:

当序列化完成后,后期推送升级程序中的类(Student), 此时再反序列化时会出现异常。

1 Exception in thread "main" java.io.InvalidClassException: cn.sxt05.serializable.Student; local class incompatible: stream classdesc serialVersionUID = -6288733824962181189, local class serialVersionUID = 1690603786167234505
2     at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)
3     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1876)
4     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1745)
5     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033)
6     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567)
7     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)

 主要原因是没有给Student类加序列化版本号, 添加了就可以解决企业版本推送更新发生版本异常问题;

添加方式有两种:

以下代码添加后版本号之后,就可以解决推送更新版本号的问题;

 1 package cn.a2.serializable;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Student implements Serializable {
 6     /**
 7      * 
 8      */
 9     private static final long serialVersionUID = -4427440848479890883L;//给Student类加序列化版本号,可以解决企业版本推送更新发生版本异常问题。    
10     
11     private String id;
12     private String name;
13     private int age;
14     private Gender gender;
15     public String getId() {
16         return id;
17     }
18     public void setId(String id) {
19         this.id = id;
20     }
21     public String getName() {
22         return name;
23     }
24     public void setName(String name) {
25         this.name = name;
26     }
27     public int getAge() {
28         return age;
29     }
30     public void setAge(int age) {
31         this.age = age;
32     }
33     public Gender getGender() {
34         return gender;
35     }
36     public void setGender(Gender gender) {
37         this.gender = gender;
38     }
39     public Student(String id, String name, int age, Gender gender) {
40         super();
41         this.id = id;
42         this.name = name;
43         this.age = age;
44         this.gender = gender;
45     }
46     public Student() {
47         super();
48     }
49     
50     @Override
51     public String toString() {
52         return "Student [id=" + id + ", name=" + name + ", age=" + age
53                 + ", gender=" + gender + "]";
54     }
55     
56 
57 }
58 
59 enum Gender {
60     男, 女;
61 
62 }

 反序列化

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.IOException;
 5 import java.io.ObjectInputStream;
 6 
 7 public class Test2 {
 8     public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
 9         File file = new File("d:"+File.separator+"javatest"+File.separator+"e.txt");
10         
11         FileInputStream iStream = new FileInputStream(file);
12         ObjectInputStream ois = new ObjectInputStream(iStream);
13         
14         Student student = (Student)ois.readObject();
15         System.out.println(student.getId());
16         System.out.println(student.getName());
17         System.out.println(student.getAge());
18         System.out.println(student.getGender());
19         
20         iStream.close();
21         ois.close();
22     }
23 
24 }

 添加后版本号之后,就可以解决了更新版本号异常问题,所以以后企业开发过程中,一定要记得添加版本号。

转载于:https://www.cnblogs.com/abcdjava/p/10834654.html

### Java序列化概念 在Java中,对象的序列化是指把对象转换成字节流的过程,以便于保存到文件或在网络上传输。反序列化则是指将这些字节流转回原始对象的过程。为了使某个类的对象能够被序列化,该类需要实现`java.io.Serializable`接口。 此接口并不提供具体的方法;它只是一个标记接口,表明实现了它的类可以参与序列化进程[^1]。当一个类未实现`Serializable`接口而试图对其进行序列化操作时,将会抛出`NotSerializableException`异常[^2]。 ### Serializable 接口使用方法 为了让一个自定义类支持序列化功能,只需让此类继承`Serializable`接口即可: ```java import java.io.*; class Person implements Serializable { private static final long serialVersionUID = 1L; String name; transient int age; // 不希望age属性被序列化 public Person(String n, int a){ this.name=n; this.age=a; } } ``` 注意,在上述例子中加入了`transient`关键字修饰成员变量`age`,这意味着即使整个类是可序列化的,但是`age`字段不会参与到序列化过程中去。另外还声明了一个名为`serialVersionUID`的静态常量来确保不同版本之间的兼容性。 对于如何实际执行序列化和反序列化过程,则可以通过如下方式完成: #### 序列化对象至文件 ```java public class SerializeDemo { public static void main(String[] args) { Person p = new Person("John", 30); try{ FileOutputStream fileOut = new FileOutputStream("/tmp/person.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(p); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/person.ser"); }catch(IOException i){ i.printStackTrace(); } } } ``` #### 从文件读取并恢复对象 ```java public class DeserializeDemo { public static void main(String[] args) { Person p = null; try{ FileInputStream fileIn = new FileInputStream("/tmp/person.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); p = (Person)in.readObject(); in.close(); fileIn.close(); } catch(Exception e){ e.printStackTrace(); return; } System.out.println("Deserialized Person..."); System.out.println("Name: " + p.name); System.out.println("Age: " + p.age); // 这里打印出来的年龄将是默认值0,因为它是瞬态(transient)的 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值