Java 瞬态字段的序列化
我正在阅读Thinking in Java 第四版。 其中描述了一种奇怪的临时解决方法:
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中包含多少这样的后门?
I am reading Thinking in Java 4th Edition.
There described a strange workaround for serialization of transient
fields:
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'}
}
}
As you can see, there are implemented private methods writeObject
and readObject
.
The questions are:
For what ObjectOutputStream and ObjectInputStream are using Reflection for accessing private methods ?
How many back doors like this are included in the Java ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
后门?它一直在规范中。这是实现对象非默认序列化的唯一方法。
非默认序列化使您处于序列化驱动程序的位置。您可以向输出流写入任何内容,只要您可以读回它并在流的另一端构造您的对象,就可以了。
事实上,这个人决定序列化瞬态字段并不是问题,关键是如果您正在实现自己的序列化方案,您可以做任何您想做的事情。
Backdoor? It's always been in the spec. It is the only way to implement non-default serialization of an object.
Non-default serialization puts you in the serialization driver's seat. You can write whatever to the output stream and as long as you can read it back and construct your object on the other end of the stream, you'll be ok.
The fact that this person decided to serialize transient fields is just not the issue, the point is that you can do whatever you want if you are implementing your own serialization scheme.
呃,它不是“后门”......您实现了一个自定义序列化,在调用忽略瞬态字段的默认序列化后将它们输出到输出流。
Erm, it isn't a "backdoor" ... you implemented a custom serialization that output the transient fields to the output stream after calling the default serialization which ignored them.
Serialized接口是标记接口。所以它就像一个标签来解释java编译器。还有其他标记接口,例如 Clonable 等。请参阅 这里了解更多信息。
然而现在 @annotations 使用得更多了。
The Serializable interface is marker interface. So its like a tag to explain the java compiler. There are other marker interfaces like Clonable, etc. See here for more.
However now a days @annotations are used more.