Given:
10. import java.io.*;
11. Class Animal {
12. Animal(){System.out.print("a");}}
13. Class Dog extends Animal implements Serializable{
14. Dog(){System.out.print("a");}}
15. public Beagle extends Dog {}If an instance of class Beagle is created, then Serialized,then deSerialized,what is result?
A. ad
B. ada
C. add
D. adad
E. Compilation fails.
F. A exception is thrown at runtime. 选哪个,原因是什么???求解
10. import java.io.*;
11. Class Animal {
12. Animal(){System.out.print("a");}}
13. Class Dog extends Animal implements Serializable{
14. Dog(){System.out.print("a");}}
15. public Beagle extends Dog {}If an instance of class Beagle is created, then Serialized,then deSerialized,what is result?
A. ad
B. ada
C. add
D. adad
E. Compilation fails.
F. A exception is thrown at runtime. 选哪个,原因是什么???求解
14. Dog(){System.out.print("d");}}
第十四行应该是这样,呵呵,笔误..
2.创建对象输出ad,序列化:就是把对象以字节形式写入文件,反序列:就是从文件里读出对象,好像之后没用到对象的创建啊,A吧,
首先在创建对象的时候输出ad
序列化的时候不会创建对象,所以不会调用任何构造函数
在反序列化的时候会重新生成对象,会调用无参数的构造函数,由于Animal类没有实现Serializable接口,所以不会调到Animal的构造函数。
最终调到Dog的构造函数,输出d
结果add
写错了,结果是ada!!!import java.io.*;class Animal {
Animal() {
System.out.print("a");
}
}class Dog extends Animal implements Serializable { private static final long serialVersionUID = 1L; Dog() {
System.out.print("d");
}
}public class Beagle extends Dog { private static final long serialVersionUID = 1L; public static void main(String[] args) {
Beagle beagle = new Beagle();
try {
FileOutputStream fos = new FileOutputStream("test.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(beagle);
oos.close();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream("test.out");
ObjectInputStream ois = new ObjectInputStream(fis);
beagle = (Beagle) ois.readObject();
ois.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}ois.readObject()说明如下
The root object is completely restored when all of its fields and the objects it references are completely restored.所以在反序列化时会生成一个root object
这句刚好写反了吧。
因为Animal没有实现Serializable接口,所以在反系列化的时候,才会调用Animal的无参构造方法来实例化Animail。
好像前两天刚写了一篇【Java Serializable系列化与反系列化】的文章。
我们要明确一点 序列化,比如我们将对象写到磁盘中,其实我们只是将对象的信息 以二进制流的形式写到文件里去,并不涉及到构造函数。
但是反序列化需要根据对象的信息在内存中重新构造对象,这就涉及到构造函数了
基类在实例化的时候 顺序 父类->基类 构造函数是按照这个个顺序执行的
以上纯属小弟的一点理解
我觉得应该是 ad
话说回来,这个题目的意图倒是比较有意思,我仔细翻了下Serializable接口的说明,其中有一段非常晦涩难懂(估计是翻译坑爹了,英文不好没办法)的解释说明了这个情况:要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和恢复超类型的公用 (public)、受保护的 (protected) 和(如果可访问)包 (package) 字段的状态。仅在子类型扩展的类有一个可访问的无参数构造方法来初始化该类的状态时,才可以假定子类型有此职责。如果不是这种情况,则声明一个类为可序列化类是错误的。该错误将在运行时检测到。
在反序列化过程中,将使用该类的公用或受保护的无参数构造方法初始化不可序列化类的字段。可序列化的子类必须能够访问无参数构造方法。可序列化子类的字段将从该流中恢复。题目期望的答案是B:ada(那个d楼主后面说了打错了)。
真要被这种题目坑到了,就选编译失败,然后跟面试官理论,一上来就指出他们不严谨,语法错误,先占点优势,哈哈,住大家面试好运!
import java.io.*;
class Animal {
Animal(){System.out.print("a");}
}
class Dog extends Animal implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L; Dog(){System.out.print("d");}
}
public class Beagle extends Dog {
/**
*
*/
private static final long serialVersionUID = 1L; /**
* @param args
*/
public static void main(String[] args) {
Beagle b = new Beagle(); }
}
当一个对象被创建时,初始化是以下面的顺序完成的:
1. 设置成员的值为缺省的初始值 (0, false, null)
2. 调用对象的构造方法 (但是还没有执行构造方法体)
3. 调用父类的构造方法
4. 使用初始化程序和初始块初始化成员
5. 执行构造方法体
看看在实际中是如何一步一步完成的,看看下面的例子:
class A {
A() {
System.out.println("A.A called");
}
}
class B extends A {
int i = f();
int j;
{
j = 37;
System.out.println("initialization block executed");
}
B() {
System.out.println("B.B called");
}
int f() {
System.out.println("B.f called");
return 47;
}
}
public class CtorDemo2 {
public static void main(String args[]) {
B bobj = new B();
}
}
程序的输出是:
A.A called
B.f called
initialization block executed
B.B called
B 的构造方法被调用,但是最先做的事情是隐含的调用父类的构造方法。父类必须自己负责初始化它自己的状态而不是让子类来做。 然后B对象的成员被初始化,这包含一个对B.f 的调用和包围在{}中的初始块的执行。最后B的构造方法体被执行。