同标题

解决方案 »

  1.   

    serialVersionUID 用来表明类的不同版本间的兼容性。Java的序列化机制是在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。 当实现Serializable接口的类没有显式地定义一个名为serialVersionUID的时候,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID 。 如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
      

  2.   

    在java中serialVersionUID是唯一控制着能否反序列化成功的标志,   只要这个值不一样,就无法反序列化成功。序列化就是 保存在内存中的各种对象的状态(也就是实例变量,不是方法),之后在某个地方可以把保存的对象状态再还原回来。一般在你想把的内存中的对象状态保存到一个文件中的时候、用套接字在网络上传送对象的时候、当你想通过RMI传输对象的时候才好用到这个东西。序列化的对象要实现 java.io.Serializable。
    给你举个例子。想要序列化的对象:
    Class 名是:Own,实现了java.io.Serializable

    package com.test.serialization;public class Own implements java.io.Serializable
    {
    private int no = 272;
    private String name = "bzwm";
    private String sex = "man";public String getName()
    {
    return name;
    }
    public void setName(String name)
    {
    this.name = name;
    }
    public int getNo()
    {
    return no;
    }
    public void setNo(int no)
    {
    this.no = no;
    }
    public String getSex()
    {
    return sex;
    }
    public void setSex(String sex)
    {
    this.sex = sex;
    }
    }
    然后用Class SaveReadOwn 来保存对象,再把它读出来。package com.test.serialization;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    public class SaveReadOwn
    {
    public static void main(String args[])
    {
      SaveReadOwn s = new SaveReadOwn();
      
      Own myself = new Own();
      
      myself.setNo(272);
      myself.setName("HIBZWM");
      myself.setSex("man");
      // change my name
      s.save(myself);
      myself.setName("other");
      System.out.println("change myname to : " + myself.getName());
      //read object
      myself = (Own)s.read("foo.ser");
      
      System.out.println("saved object : myName = " + myself.getName());
    }
    // save
    public void save(Own foo)
    {
      try
      {
       FileOutputStream fos = new FileOutputStream("foo.ser");
       ObjectOutputStream oos = new ObjectOutputStream(fos);
       oos.writeObject(foo);
       fos.close();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
    }
    //read
    public Object read(String objPath)
    {
      Object foo = null;
      try
      {
       FileInputStream fis = new FileInputStream(objPath);
       ObjectInputStream ois = new ObjectInputStream(fis);
       foo = ois.readObject();
       ois.close();
       fis.close();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
      return foo;
    }
    }运行结果自己看吧。
      

  3.   

    接着我修改这两个类。首先 SaveReadOwn 类我不做save 处理,我只想把 “楼上的代码” 里保存的对象反序列化回来。
    代码如下:
    package com.test.serialization;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    public class SaveReadOwn
    {
    public static void main(String args[])
    {
      SaveReadOwn s = new SaveReadOwn();
      
      Own myself = null;//new Own();
      
    //  myself.setNo(272);
    //  myself.setName("HIBZWM");
    //  myself.setSex("man");
      // change my name
    //  s.save(myself);
    //  myself.setName("other");
    //  System.out.println("change myname to : " + myself.getName());
      //read object
      myself = (Own)s.read("foo.ser");
      
      System.out.println("saved object : myName = " + myself.getName());
    }
    // save
    public void save(Own foo)
    {
      try
      {
       FileOutputStream fos = new FileOutputStream("foo.ser");
       ObjectOutputStream oos = new ObjectOutputStream(fos);
       oos.writeObject(foo);
       fos.close();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
    }
    //read
    public Object read(String objPath)
    {
      Object foo = null;
      try
      {
       FileInputStream fis = new FileInputStream(objPath);
       ObjectInputStream ois = new ObjectInputStream(fis);
       foo = ois.readObject();
       ois.close();
       fis.close();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
      return foo;
    }
    }
    此时我只修改了 用来读取对象的类,然后执行,结果你自己试试。接着,我把类 Own 修改一下,加一个字段 private final int test = 0;package com.test.serialization;
    public class Own implements java.io.Serializable
    {
    private int no = 272;
    private String name = "bzwm";
    private String sex = "man";
    private final int test = 0;
    public String getName()
    {
      return name;
    }
    public void setName(String name)
    {
      this.name = name;
    }
    public int getNo()
    {
      return no;
    }
    public void setNo(int no)
    {
      this.no = no;
    }
    public String getSex()
    {
      return sex;
    }
    public void setSex(String sex)
    {
      this.sex = sex;
    }
    }然后你再执行一下,就会报错了。
    类似 这样的信息:
    java.io.InvalidClassException: com.test.serialization.Own; local class incompatible: stream classdesc serialVersionUID = 7794841109938881749, local class serialVersionUID = 6646693911615467598
    继续修改类 Own,加一个字段:private static final long serialVersionUID = 7794841109938881749l;(强制修改uid)

    package com.test.serialization;public class Own implements java.io.Serializable
    {
    private int no = 272;
    private String name = "bzwm";
    private String sex = "man";
    private final int test = 0;private static final long serialVersionUID = 7794841109938881749l;public String getName()
    {
    return name;
    }
    public void setName(String name)
    {
    this.name = name;
    }
    public int getNo()
    {
    return no;
    }
    public void setNo(int no)
    {
    this.no = no;
    }
    public String getSex()
    {
    return sex;
    }
    public void setSex(String sex)
    {
    this.sex = sex;
    }
    }再执行,看结果吧。