一个关于对象序列化的怪题。。。求解答

bibihenmuc 2010-04-08 10:32:21
程序如下
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Test {

public static void main(String[] args) throws Exception {
Banana2 b = new Banana2();
File file = new File("d:/test.txt");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
oos.writeObject(b);
oos.close();
ois.readObject();
ois.close();
System.out.println( " restored " + b.size + " " );
}
}

class Food {
Food() {
System.out.print(" 1 ");
}
}

class Fruit extends Food implements Serializable {
private static final long serialVersionUID = 2387924016119347282L;

Fruit() {
System.out.print(" 2 ");
}
}

class Banana2 extends Fruit {
private static final long serialVersionUID = 7689053551729518274L;
int size = 42;
}

运行结果: 1 2 1 restored 42
谁解释哈1 2后面那个1怎么出的啊,我百思不得其解。。。。。。。。。。
...全文
164 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wingardium 2010-04-09
  • 打赏
  • 举报
回复
解序列会调用一个隐藏的构造器,这个构造器和一般显式的一样,会首先调用super()。这就是为什么会打印出Food里面的1;没有再打印出显式构造器中的2.
Rosecui 2010-04-09
  • 打赏
  • 举报
回复
不知道啊,等高手解决。很有意思
laker_914 2010-04-09
  • 打赏
  • 举报
回复
查一下API,ObjectInputStream

里面有说明,对序列化和反序列化的
若鱼1919 2010-04-09
  • 打赏
  • 举报
回复
因为Food不可以序列化,而读出来的是一个Banana2,Banana2是可以序列化的,Fruit也是可以序列化的,所以需要构造一个初始的Food。
church88 2010-04-09
  • 打赏
  • 举报
回复
等高手解答
bibihenmuc 2010-04-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sharke118 的回复:]
在java 序列化中 允许非序列化类的子类型序列化,子类型可以假定负责保存和恢复父类型的公有的、保护的和(如果可访问)包的域的状态。只要该类(扩展)有一个无参构造子,可初始化它的状态,那么子类型就可承担上述职责。也就是说Food类不可序列化 但Banana2 可以序列化 Banana2 是Food的子类 它负责保存和恢复Food类相关的域的状态 当Banana2类反序列化得时候 会调用Food的构……
[/Quote]
个人觉得这种解释比较合理,
这就是sun的scjp考试的考题,考的都是一些变态题,郁闷啊。。。。。。
wingardium 2010-04-09
  • 打赏
  • 举报
回复
我对你的代码加了点料,把Food类改成如下所示(其它类不变):

class Food{
Food() {
System.out.print(" 1 ");
new Exception().printStackTrace();
}
}


运行后打印出方法栈如下:
java.lang.Exception
at Food.<init>(Test.java:26)
at sun.reflect.GeneratedSerializationConstructorAccessor2.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.io.ObjectStreamClass.newInstance(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at Test.main(Test.java:17)
=================================================================================
接下来保持Food类如上不变,将实现Serializable接口的类改成Banana2,运行,打印如下:

java.lang.Exception
at Food.<init>(Test.java:26)
at Fruit.<init>(Test.java:33)
at sun.reflect.GeneratedSerializationConstructorAccessor1.newInstance(Uknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.io.ObjectStreamClass.newInstance(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at Test.main(Test.java:17)
你可能注意到了两次动态创建的隐藏构造器是不一样的。暂时我也就挖掘到这里。。。。。。
wingardium 2010-04-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sharke118 的回复:]
在反序列化的时候 它的对象其实本来就是存在的 只需要反序列化恢复成对象就可以了 不需要再调用构造函数实例化[/Quote]

反序列化出来的,只会有一个Banana2实例,不会有Fruit实例出现,更不会有Food的实例出现。请注意,调用父类的构造函数(即super()),不会创建一个父类的实例。在jvm指令集中,super()对应的指令是invokespecial, 创建实例只有一个指令,那就是new。
sharke118 2010-04-09
  • 打赏
  • 举报
回复
在java 序列化中 允许非序列化类的子类型序列化,子类型可以假定负责保存和恢复父类型的公有的、保护的和(如果可访问)包的域的状态。只要该类(扩展)有一个无参构造子,可初始化它的状态,那么子类型就可承担上述职责。也就是说Food类不可序列化 但Banana2 可以序列化 Banana2 是Food的子类 它负责保存和恢复Food类相关的域的状态 当Banana2类反序列化得时候 会调用Food的构造函数 实例化Food类 这时就会输出值 1 ,而对Fruit 类而言虽然它也是Banana2的父类 但是它是可以序列化的 在反序列化的时候 它的对象其实本来就是存在的 只需要反序列化恢复成对象就可以了 不需要再调用构造函数实例化 楼主可以试试 把Food类改成可以序列化 的 而它的两级子类Fruit 和 Banana2不再明文实现Serializable接口 结果按上面所说 就应该是 1 2 restored 42 如果把Food 和 Fruit类改成不可序列化 那么结果就是 1 2 1 2 restored 42
bibihenmuc 2010-04-08
  • 打赏
  • 举报
回复
顺便问一下,在这个论坛帖子中插入怎么插入代码啊,让代码有单独的显示区域

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧