序列化ID的作用:  

       序列化ID决定:是否能够成功反序列化!简单来说,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。等会我们可以通过代码验证一下。

       序列化ID如何产生:

       当我们一个实体类中没有显示的定义一个名为“serialVersionUID”、类型为long的变量时,Java序列化机制会根据编译时的class自动生成一个serialVersionUID作为序列化版本比较,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID。譬如,当我们编写一个类时,随着时间的推移,我们因为需求改动,需要在本地类中添加其他的字段,这个时候再反序列化时便会出现serialVersionUID不一致,导致反序列化失败。那么如何解决呢?便是在本地类中添加一个“serialVersionUID”变量,值保持不变,便可以进行序列化和反序列化。

       验证“serialVersionUID”不一致导致反序列化失败

1. import java.io.Serializable;  
2.   
3. /**
4.  * 
5.  * 测试序列化和反序列化
6.  * @author crazyandcoder
7.  * @date [2015-8-5 上午11:14:32]
8.  */
9. public class Person implements Serializable  {  
10.       
11.     private int age;  
12. //  private String sex;
13. //  private String name;
14. //  private String hobby;
15. //序列化ID
16. //  private static final long serialVersionUID = -5809782578272943999L;
17.       
18. //  public String getHobby() {
19. //      return hobby;
20. //  }
21. //
22. //  public void setHobby(String hobby) {
23. //      this.hobby = hobby;
24. //  }
25.   
26.     public Person() {}  
27.       
28.     public int getAge() {  
29.         return age;  
30.     }  
31.       
32.     public void setAge(int age) {  
33.         this.age = age;  
34.     }  
35.       
36. //  public String getSex() {
37. //      return sex;
38. //  }
39. //
40. //  public void setSex(String sex) {
41. //      this.sex = sex;
42. //  }
43.       
44. //  public String getName() {
45. //      return name;
46. //  }
47. //  public void setName(String name) {
48. //      this.name = name;
49. //  }
50.   
51. }

        复用前篇使用到的代码,首先,我们生成一个本地Person类,里面添加一个字段age,然后将其序列化存于本地E:/hello.txt中,

1. import java.io.FileNotFoundException;  
2. import java.io.FileOutputStream;  
3. import java.io.IOException;  
4. import java.io.ObjectOutputStream;  
5.   
6.   
7. /**
8.  * 
9.  * 测试序列化和反序列化
10.  * @author crazyandcoder
11.  * @date [2015-8-5 上午11:16:14]
12.  */
13. public class ObjSerializeAndDeserializeTest {  
14.   
15.        
16.     public static void main(String[] args) {  
17.           
18. //将Person对象序列化
19.         SerializePerson();  
20.     }  
21.       
22.       
23. /**
24.      * 
25.      * @author crazyandcoder
26.      * @Title: 序列化Person对象,将其存储到 E:/hello.txt文件中
27.      * @param  
28.      * @return void 
29.      * @throws 
30.      * @date [2015-8-5 上午11:21:27]
31.      */
32.     private static void SerializePerson() {  
33.         Person person =new Person();  
34. 30);  
35.         ObjectOutputStream outputStream = null;  
36.         try {  
37.             outputStream=new ObjectOutputStream(new FileOutputStream("E:/hello.txt"));  
38.             outputStream.writeObject(person);  
39. "序列化成功。");  
40.         } catch (FileNotFoundException e) {  
41.             e.printStackTrace();  
42.                   
43.         } catch (IOException e) {  
44.             e.printStackTrace();  
45.                   
46.         } finally {  
47.             try {  
48.                 outputStream.close();  
49.             } catch (IOException e) {  
50.                 e.printStackTrace();  
51.             }  
52.         }  
53.           
54.     }  
55. }

        运行一下,会在控制台中打印“序列化成功。”,然后我们在Person类中再添加一个字段,name,然后直接从E:/hello.txt中反序列化,再运行一下,看看会出现什么问题。

1. import java.io.FileInputStream;  
2. import java.io.FileNotFoundException;  
3. import java.io.FileOutputStream;  
4. import java.io.IOException;  
5. import java.io.ObjectInputStream;  
6. import java.io.ObjectOutputStream;  
7.   
8. /**
9.  * 
10.  * 测试序列化和反序列化
11.  * 
12.  * @author crazyandcoder
13.  * @date [2015-8-5 上午11:16:14]
14.  */
15. public class ObjSerializeAndDeserializeTest {  
16.   
17.     public static void main(String[] args) {  
18.   
19. // 反序列化生成Person对象
20.         Person person = DeserializePerson();  
21. "name :"
22. "age  :"
23.     }  
24.   
25. /**
26.      * 执行反序列化过程生产Person对象
27.      * 
28.      * @author crazyandcoder
29.      * @Title: DeserializePerson
30.      * @param @return
31.      * @return Person
32.      * @throws
33.      * @date [2015-8-5 下午1:30:12]
34.      */
35.     private static Person DeserializePerson() {  
36.   
37.         Person person = null;  
38.         ObjectInputStream inputStream = null;  
39.         try {  
40.             inputStream = new ObjectInputStream(new FileInputStream("E:/hello.txt"));  
41.             try {  
42.                 person = (Person) inputStream.readObject();  
43. "执行反序列化过程成功。");  
44.             } catch (ClassNotFoundException e) {  
45.                 e.printStackTrace();  
46.             }  
47.         } catch (FileNotFoundException e) {  
48.             e.printStackTrace();  
49.         } catch (IOException e) {  
50.             e.printStackTrace();  
51.         } finally {  
52.             try {  
53.                 inputStream.close();  
54.             } catch (IOException e) {  
55.                 e.printStackTrace();  
56.             }  
57.         }  
58.         return person;  
59.     }  
60. }

       运行一下,不出意外,报了一个异常。

 

java 分配id java中id是什么意思_java 分配id

java 分配id java中id是什么意思_java 分配id_02

        从上面两张图便可以看出两次的序列化ID是不一样的,导致反序列化失败。

总结:

       虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。