java 序列化ID的作用

您所在的位置:网站首页 接口id是什么 java 序列化ID的作用

java 序列化ID的作用

2024-06-02 14:58| 来源: 网络整理| 查看: 265

java 序列化ID的作用

       有关序列化和反序列化的概念,可以查看前一篇《java序列化和反序列化使用总结》的讲解,这一篇主要说明一下序列化过程中出现的问题即java序列化和反序列化中ID的作用。

        在前一篇的介绍中,我们在代码里会发现有这样一个变量:serialVersionUID,那么这个变量serialVersionUID到底具有什么作用呢?能不能去掉呢?

public class Person implements Serializable { private int age; private String sex; private String name; private String hobby; //序列化ID private static final long serialVersionUID = -5809782578272943999L; ............ }       

       序列化ID的作用:  

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

       序列化ID如何产生:

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

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

import java.io.Serializable; /** * * 测试序列化和反序列化 * @author crazyandcoder * @date [2015-8-5 上午11:14:32] */ public class Person implements Serializable { private int age; // private String sex; // private String name; // private String hobby; //序列化ID // private static final long serialVersionUID = -5809782578272943999L; // public String getHobby() { // return hobby; // } // // public void setHobby(String hobby) { // this.hobby = hobby; // } public Person() {} public int getAge() { return age; } public void setAge(int age) { this.age = age; } // public String getSex() { // return sex; // } // // public void setSex(String sex) { // this.sex = sex; // } // public String getName() { // return name; // } // public void setName(String name) { // this.name = name; // } }         复用前篇使用到的代码,首先,我们生成一个本地Person类,里面添加一个字段age,然后将其序列化存于本地E:/hello.txt中,

import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /** * * 测试序列化和反序列化 * @author crazyandcoder * @date [2015-8-5 上午11:16:14] */ public class ObjSerializeAndDeserializeTest { public static void main(String[] args) { //将Person对象序列化 SerializePerson(); } /** * * @author crazyandcoder * @Title: 序列化Person对象,将其存储到 E:/hello.txt文件中 * @param * @return void * @throws * @date [2015-8-5 上午11:21:27] */ private static void SerializePerson() { Person person =new Person(); person.setAge(30); ObjectOutputStream outputStream = null; try { outputStream=new ObjectOutputStream(new FileOutputStream("E:/hello.txt")); outputStream.writeObject(person); System.out.println("序列化成功。"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }         

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

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * * 测试序列化和反序列化 * * @author crazyandcoder * @date [2015-8-5 上午11:16:14] */ public class ObjSerializeAndDeserializeTest { public static void main(String[] args) { // 反序列化生成Person对象 Person person = DeserializePerson(); System.out.println("name :" + person.getName()); System.out.println("age :" + person.getAge()); } /** * 执行反序列化过程生产Person对象 * * @author crazyandcoder * @Title: DeserializePerson * @param @return * @return Person * @throws * @date [2015-8-5 下午1:30:12] */ private static Person DeserializePerson() { Person person = null; ObjectInputStream inputStream = null; try { inputStream = new ObjectInputStream(new FileInputStream("E:/hello.txt")); try { person = (Person) inputStream.readObject(); System.out.println("执行反序列化过程成功。"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return person; } }        运行一下,不出意外,报了一个异常。

      

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

总结:

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3