【发布时间】:2011-04-15 20:54:39
【问题描述】:
我正在阅读 Thinking in Java 4th Edition。
那里描述了transient 字段序列化的奇怪解决方法:
import java.io.*;
public class SerializationTest implements Serializable {
private String firstData;
//transient field, shouldn't be serialized.
transient private String secondData;
public SerializationTest(String firstData, String test2) {
this.firstData = firstData;
this.secondData = test2;
}
/**
* Private method, same signature as in Serializable interface
*
* @param stream
* @throws IOException
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(secondData);
}
/**
* Private method, same signature as in Serializable interface
*
* @param stream
* @throws IOException
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
secondData = (String) stream.readObject();
}
@Override
public String toString() {
return "SerializationTest{" +
"firstData='" + firstData + '\'' +
", secondData='" + secondData + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("object.out");
oos = new ObjectOutputStream(fos);
SerializationTest sTest = new SerializationTest("First Data", "Second data");
oos.writeObject(sTest);
} finally {
oos.close();
fos.close();
}
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("object.out");
ois = new ObjectInputStream(fis);
SerializationTest sTest = (SerializationTest) ois.readObject();
System.out.println(sTest);
} finally {
ois.close();
fis.close();
}
//Output:
//SerializationTest{firstData='First Data', secondData='Second data'}
}
}
如您所见,实现了私有方法writeObject 和readObject。
问题是:
ObjectOutputStream 和 ObjectInputStream 使用反射访问私有方法的原因是什么?
Java 中包含多少这样的后门?
【问题讨论】:
-
顺便说一句,您的资源处理不正确。标准格式为:
Resource resource = acquire(); try { use(resource); } finally { resource.release(); }。您应该为每个资源单独执行此操作。在 Java SE 6 中,大多数情况下您可以编写try (Resource resource = acquire()) { use(resource); }。没有必要关闭你的对象流,除了只在快乐的情况下刷新ObjectOutputStream(也就是说在try的主体中;在finally中刷新也会在错误情况下这样做,这并不是你真正想要的)。 -
@Tom:
try(...){语法已经在 Java SE 6 中了?这对我来说是新的,我以为只有 7 个。 -
@Paŭlo Ebermann 错字。应阅读“在 Java SE 7 中”。 (而且你不应该使用
-target 1.6 -source 1.7。除了目标需要至少与源一样最新的规则之外,它还需要额外的库支持。也许 Retroweaver 或类似的东西会破解。)
标签: java serialization reflection