当我遇到保存不可序列化的对象状态并在Class(实例变量)中引用以进行序列化时,我正在研究Java中的序列化。在下面的代码中,我有类Dog(Serializable),它引用了类Collar(不可序列化);而这又引用了类Color(不可序列化)。尽管尝试了所有的可能性,但我收到了错误。这是我提出的最新代码:
class Color {
private String colorName;
public String getColorName() {
return colorName;
}
public void setColorName(String colorName) {
this.colorName = colorName;
}
Color(String color) {
this.colorName = color;
}
}
class Collar {
private Color color;
private int size;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
Collar(int size, Color color) {
this.size = size;
this.color = color;
}
}
class Dog implements Serializable {
Dog(String breed, Collar collar) {
this.breed = breed;
this.collar = collar;
}
private String breed;
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public Collar getCollar() {
return collar;
}
public void setCollar(Collar collar) {
this.collar = collar;
}
transient private Collar collar;
private void writeObject(ObjectOutputStream os) {
try {
os.defaultWriteObject();
os.writeInt(this.getCollar().getSize());
os.writeUTF(this.getCollar().getColor().getColorName());
os.close();
} catch (IOException ex) {
Logger.getLogger(Dog.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void readObject(ObjectInputStream is) {
try {
is.defaultReadObject();
int size = is.readInt();
String colorName = is.readUTF();
this.setCollar(new Collar(size, new Color(colorName)));
is.close();
} catch (Exception ex) {
Logger.getLogger(Dog.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class App0001 {
public static void main(String[] args) {
try {
Dog d = new Dog("Great Dane", new Collar(3, new Color("RED")));
//System.out.println(d.getCollar().getColor().getColorName());
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("obj.ser"));
os.writeObject(d);
os.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("obj.ser"));
d = (Dog) is.readObject();
System.out.println(d.getCollar().getColor().getColorName());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
我收到了以下错误:
java.io.IOException: Write error
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:260)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1847)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1756)
at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1257)
at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1211)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1395)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:333)
at Serialization.App0001.main(App0001.java:121)
这不是生产代码。这只是为了练习和理解。
答案 0 :(得分:2)
您不得关闭readObject
和writeObject
中的信息流!如果这样做,则下一次写入/读取尝试失败。
通常,流(作为其他资源)应按如下方式处理:
try-with-resource
statement中完成)。答案 1 :(得分:1)
写入流时,如果流已关闭,则会出现IOException
中的“写入错误”。
分析您的代码,我发现您的班级writeObject
中有自定义Dog
方法。因此,您不能关闭流,因为它是继续写入所必需的。所以只需删除
os.close();
在您的writeObject
方法中。哦,还删除了行
is.close();
在readObject
方法中。
好的,我会再解释一下。主方法中包含以下代码:
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("obj.ser"));
os.writeObject(d);
os.close();
在这里,您正在使用它创建流,然后关闭它。这是关闭它的正确位置,因为这是流的负责地点。
想象一下,您有一个可序列化对象的嵌套结构,其类定义都包含自定义writeObject
方法。在调用ObjectOutputStream
的writeObject方法时,它通过调用每个对象的writeObject
方法遍历对象图。 ObjectOutputStream
控制写入顺序,它也自己写入控制字节。创建和关闭必须在外面完成(正如您已经做过的那样)。