1、如果超类没有实现Serializable接口,子类就一定要实现该接口才能实现对象串行化。而且还要保证超类里有无参数的构造方法,为什么要有这样的要求?我举一个例子,大家可以根据这个实例来讨论:import java.io.*;
//如果超类因没有实现 Serializable 接口而不可串行化,则子类
//必须实现 Serializable 接口,且超类必须具有无参构造方法。
//假定子类对象的超类部分不需要串行化:
class Super2{
private int int_field; //基本类型都是可串行化类型
private double double_field; public Super2(int i, double d){
int_field=i;
double_field=d;
}// 因没有实现 Serializable 接口,必须定义无参构造方法
public Super2(){
this(0,0.0);
} public int getInt(){
return int_field;
} public void setInt(int i){
int_field=i;
} public double getDouble(){
return double_field;
} public void setDouble(double d){
double_field=d;
} public String toString(){
return "Super2: "+int_field+","+double_field;
}
}class Sub2 extends Super2 implements Serializable{
private String string_field; //String 是可串行化字类型 public Sub2(int i, double d, String s){
super(i,d);
string_field=s;
} public String getString(){
return string_field;
} public void setString(String s){
string_field=s;
} //因为超类和子类的要进行串行化的变量都定已成为了private访问权限,因此必须在“写入”操作时调用get()函数来获得他们的值
private void writeObject(ObjectOutputStream out)throws IOException{
//通过超类提供的访问其成员变量的方法(get()方法),将超类的成员变量写入
out.writeInt(getInt()); //getInt()方法是超类提供的
out.writeDouble(getDouble()); //getDouble()方法是超类提供的
out.writeUTF(getString());
}
//因为超类和子类的要进行串行化的变量都定已成为了private访问权限,因此必须在“读出”操作时调用set()函数来改变他们的值
private void readObject(ObjectInputStream in)throws IOException{
//通过超类提供的设置其成员变量的方法(set()方法),将其超类的成员读出,实际上是设置成员变量的值
setInt(in.readInt()); //setInt()方法是超类提供的
setDouble(in.readDouble()); //setDouble()方法是子类提供的
setString(in.readUTF());
}
public String toString(){
return "Sub2: "+string_field+" + "+super.toString();
}
}class stest2{
public static void main(String[] args){
Super2 sub=new Sub2(5,7.3,"Hello!"); System.out.println(sub); try{
ByteArrayOutputStream ba=new ByteArrayOutputStream(500);
ObjectOutputStream out=new ObjectOutputStream(ba);
out.writeObject(sub); sub=null; ObjectInputStream in=new ObjectInputStream(new ByteArrayInputStream(ba.toByteArray()));
sub=(Sub2)in.readObject();
}catch(Exception e){
System.err.println("Error found: "+e);
System.exit(1);
} System.out.println(sub);
}
}
//如果超类因没有实现 Serializable 接口而不可串行化,则子类
//必须实现 Serializable 接口,且超类必须具有无参构造方法。
//假定子类对象的超类部分不需要串行化:
class Super2{
private int int_field; //基本类型都是可串行化类型
private double double_field; public Super2(int i, double d){
int_field=i;
double_field=d;
}// 因没有实现 Serializable 接口,必须定义无参构造方法
public Super2(){
this(0,0.0);
} public int getInt(){
return int_field;
} public void setInt(int i){
int_field=i;
} public double getDouble(){
return double_field;
} public void setDouble(double d){
double_field=d;
} public String toString(){
return "Super2: "+int_field+","+double_field;
}
}class Sub2 extends Super2 implements Serializable{
private String string_field; //String 是可串行化字类型 public Sub2(int i, double d, String s){
super(i,d);
string_field=s;
} public String getString(){
return string_field;
} public void setString(String s){
string_field=s;
} //因为超类和子类的要进行串行化的变量都定已成为了private访问权限,因此必须在“写入”操作时调用get()函数来获得他们的值
private void writeObject(ObjectOutputStream out)throws IOException{
//通过超类提供的访问其成员变量的方法(get()方法),将超类的成员变量写入
out.writeInt(getInt()); //getInt()方法是超类提供的
out.writeDouble(getDouble()); //getDouble()方法是超类提供的
out.writeUTF(getString());
}
//因为超类和子类的要进行串行化的变量都定已成为了private访问权限,因此必须在“读出”操作时调用set()函数来改变他们的值
private void readObject(ObjectInputStream in)throws IOException{
//通过超类提供的设置其成员变量的方法(set()方法),将其超类的成员读出,实际上是设置成员变量的值
setInt(in.readInt()); //setInt()方法是超类提供的
setDouble(in.readDouble()); //setDouble()方法是子类提供的
setString(in.readUTF());
}
public String toString(){
return "Sub2: "+string_field+" + "+super.toString();
}
}class stest2{
public static void main(String[] args){
Super2 sub=new Sub2(5,7.3,"Hello!"); System.out.println(sub); try{
ByteArrayOutputStream ba=new ByteArrayOutputStream(500);
ObjectOutputStream out=new ObjectOutputStream(ba);
out.writeObject(sub); sub=null; ObjectInputStream in=new ObjectInputStream(new ByteArrayInputStream(ba.toByteArray()));
sub=(Sub2)in.readObject();
}catch(Exception e){
System.err.println("Error found: "+e);
System.exit(1);
} System.out.println(sub);
}
}
========================================
如果不显式的写构造函数,则编译器给你一个默认的构造函数如果显式的写了构造函数,则编译器不会提供默认的构造函数了;
这意味着如果你写的是由参数的构造函数,
而这个类又要有子类,它必须显示的写上无参数的构造函数;
因为编译器会在子类的构造函数的开始处增加super()
子类的构造函数的第一句话会隐式调用超类的无参数构造函数,但是如果子类的构造函数的第一句话是显式调用超类的有参数构造函数,就没有任何问题了。
我们之所以要在超类中定义一个无参数的构造函数,就是以免“子类构造函数的第一句话没有显式调用超类的任何构造函数”这样的情况发生而产生不必要的错误,但是请你仔细看看我上面这个例子的子类的构造函数:
public Sub2(int i, double d, String s){
super(i,d); //这里已经显式调用了超类的构造函数,因此没有任何问题
string_field=s;
}请你把注意力放在“串行化”上,为什么串行化上会有这样的要求?
如果父类没有无参构造函数,相当禁止子类序列化