A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杜鹏云 中级黑马   /  2012-8-24 17:27  /  1992 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杜鹏云 于 2012-8-24 17:29 编辑

Person类实现Serializable接口,编译器会提出这样的警告:
serializable 类 Person 未声明类型为 long 的静态终态 serialVersionUID 字段
按照编辑器的提示,选择第一个修正提示时会出现这么个提示(见下图--提示图)

这个对话框提示是什么意思?选择不同的选项,会有什么影响??

class Person implements Serializable
{
      
//private static final long serialVersionUID = 8015816128546794345L;这个是按照第一个修正方法,添加缺省串行标识
  //private static final long serialVersionUID = 1L; 这个是按照第二个修正方法,添加已生成串行标识
// 问题是:为何要添加这个serialVersionUID ,不添加有何影响,这两种不同的添加方式有何异同
        private  int  age=10;
        public  String name="张三";
  public Person() {
               
        }
        
        public Person(int age, String name) {
                this.setAge(age);
                this.name = name;
        }
        
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
  public int getAge() {
   return age;
  }
  public void setAge(int age) {
   this.age = age;
  }
   
   
}

警告标示.png (5.25 KB, 下载次数: 19)

警告标示.png

提示.png (8.94 KB, 下载次数: 15)

提示

提示

点评

原文说反了, 8015816128546794345L;第一个修正方法,添加已生成串行标识 1L; 第二个,添加缺省串行标识  发表于 2012-8-24 21:26

评分

参与人数 1技术分 +1 收起 理由
田建 + 1 恭喜!

查看全部评分

3 个回复

倒序浏览
本帖最后由 寇龙飞 于 2012-8-24 21:22 编辑

你应该看了老毕讲的IO对象序列化
先贴两个类的代码
这个问题演示的步骤文字表达起来比较繁琐,不明原理的话看着很容易晕。建议你最好去看着老毕的视频思考下。
  1. package com.itheima.test;

  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.ObjectInputStream;
  5. import java.io.ObjectOutputStream;

  6. public class ObjectStreamTest {

  7.         public static void main(String[] args) throws Exception {
  8.                 //writeObj();
  9.                 readObj();
  10.         }
  11.         
  12.         public static void readObj() throws Exception {
  13.                
  14.                 ObjectInputStream ois = new ObjectInputStream(
  15.                                 new FileInputStream("MyPerson.object"));
  16.                
  17.                 MyPerson p = (MyPerson)ois.readObject();
  18.                 System.out.println(p);
  19.                
  20.                 ois.close();
  21.         }
  22.         
  23.         public static void writeObj() throws Exception {
  24.                
  25.                 ObjectOutputStream oos = new ObjectOutputStream(
  26.                                 new FileOutputStream("MyPerson.object"));
  27.                
  28.                 oos.writeObject(new MyPerson("zhangsan", 29));
  29.                
  30.                 oos.close();
  31.         }
  32. }

复制代码
  1. package com.itheima.test;

  2. import java.io.Serializable;

  3. class MyPerson implements Serializable {

  4.         /**
  5.          *
  6.          */
  7.         private static final long serialVersionUID = -6527801543108636145L;
  8.         /**
  9.          *
  10.          */

  11.         //private static final long serialVersionUID = 1L;
  12.         
  13.         private String name;
  14.         public int age;
  15.         
  16.         public MyPerson(String name, int age) {
  17.                 super();
  18.                 this.name = name;
  19.                 this.age = age;
  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.         @Override
  34.         public String toString() {
  35.                 return "MyPerson [name=" + name + ", age=" + age + "]";
  36.         }        
  37. }
复制代码
运行结果:
  1. MyPerson [name=zhangsan, age=29]
复制代码
我把MyPerson类的属性name的权限修改为privat后,运行,报错结果为:
  1. Exception in thread "main" java.io.InvalidClassException: com.itheima.test.MyPerson; local class incompatible: stream classdesc serialVersionUID = 6549094864754487897, local class serialVersionUID = -6527801543108636145
  2.         at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)
  3.         at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)
  4.         at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
  5.         at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
  6.         at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
  7.         at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
  8.         at com.itheima.test.ObjectStreamTest.readObj(ObjectStreamTest.java:20)
  9.         at com.itheima.test.ObjectStreamTest.main(ObjectStreamTest.java:12)
复制代码
太长了,先发了,下个楼层来回答你的几个疑问。
回复 使用道具 举报
来回答你的问题:
1.eclipse提供的第一个解决方案,
  1. private static final long serialVersionUID = 8015816128546794345L;
复制代码
添加已生成串行标识,这个表示就是由你修改前的Person类文件得来的
你看我的代码中有,
  1. private static final long serialVersionUID = -6527801543108636145L;

复制代码
这个我也是用eclipse的第一个解决方案添加的,在此之前,eclipse报错说
  1. local class serialVersionUID = -6527801543108636145

复制代码
看看这二个 serialVersionUID的值是不是相同。这下该能理解了吧。
2.eclipse提供的第二个修正方案,添加缺省串行标识,serialVersionUID = 1L,为什么是1L呢?
这就像MyPerson类中属性name默认值是null,age默认值是0一样。
3.为什么要添加这个serialVersionUID呢?
为了序列化方便,MyPerson新的类还能去操作曾经被序列化的对象。这个去看老毕视频,很详细。
二者有何不同?
第一个修正方案serialVersionUID的值不会重复
第二个修正方案serialVersionUID的值1L,呵呵,你说呢?

评分

参与人数 1技术分 +1 收起 理由
田建 + 1 赞一个!

查看全部评分

回复 使用道具 举报
添加串行标识相当于给类编写了一个版本号,当我们将实例对象进行持久化存储后,在下一个不确定时间进行访问时。程序首先会去检查返回对象版本号和当前对应类的版本号是否相同。串行标识是由类属性,方法等元素通过某种方式计算出来的,当我们将类成员修改之后,系统会重新生成一个标识符,如果这时候再去访问早期存储的对象,就会报版本不同异常。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马