这篇文章很直接,简单易懂。尝试着翻译一下
,原文是
What are writeObject and readObject? Customizing the serialization process.
在Java中使用Serialization相当简单。如果你有一些对象想要进行序列化,你只需实现Serializable接口。然后,你可以使用ObjectOutputStream将该对象保存至文件或发送到其他主机。所有的non-transient和non-static字段都将被序列化,并且由反序列化重构造出一模一样的对象联系图(譬如许多引用都指向该对象)。但有时你可能想实现你自己的对象序列化和反序列化。那么你可以在某些特定情形下得到更多的控制。来看下面的简单例子。
class SessionDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int data; // Stores session data
// Session activation time (creation, deserialization)
private long activationTime;
public SessionDTO(int data) {
this.data = data;
this.activationTime = System.currentTimeMillis();
}
public int getData() {
return data;
}
public long getActivationTime() {
return activationTime;
}
}
以下是序列化上述class到文件和其反序列化的主函数。
public class SerializeTester implements Serializable {
public static void main(String... strings) throws Exception {
File file = new File("out.ser");
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
SessionDTO dto = new SessionDTO(1);
oos.writeObject(dto);
oos.close();
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
SessionDTO dto = (SessionDTO) ois.readObject();
System.out.println("data : " + dto.getData()
+ " activation time : " + dto.getActivationTime());
ois.close();
}
}
类SessionDTO展现的是要在两个服务器之间传输的session。它包含了一些信息在字段data上,该字段需要被序列化。但是它还有另外一个字段activationTime,该字段应该是session对象第一次出现在任意服务器上的时间。它不在我们想要传输的信息之列。这个字段应该在反序列化之后在赋值。进一步来说,没必要把它放在stream中在服务器中传递,因为它占据了不必要的空间。
解决这种情况可以使用writeObject和readObject。有可能你们有一些人没有听说过它们,那是因为它们在许多Java书籍中给忽略了,而且它们们也不是众多流行Java考试的一部分。让我们用这些方法来重写SessionDTO:
class SessionDTO implements Serializable {
private static final long serialVersionUID = 1L;
private transient int data; // Stores session data
//Session activation time (creation, deserialization)
private transient long activationTime;
public SessionDTO(int data) {
this.data = data;
this.activationTime = System.currentTimeMillis();
}
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeInt(data);
System.out.println("session serialized");
}
private void readObject(ObjectInputStream ois) throws IOException,
ClassNotFoundException {
ois.defaultReadObject();
data = ois.readInt();
activationTime = System.currentTimeMillis();
System.out.println("session deserialized");
}
public int getData() {
return data;
}
public long getActivationTime() {
return activationTime;
}
}
方法writeObject处理对象的序列化。如果声明该方法,它将会被ObjectOutputStream调用而不是默认的序列化进程。如果你是第一次看见它,你会很惊奇尽管它们被外部类调用但事实上这是两个private的方法。并且它们既不存在于java.lang.Object,也没有在Serializable中声明。那么ObjectOutputStream如何使用它们的呢?这个吗,ObjectOutputStream使用了反射来寻找是否声明了这两个方法。因为ObjectOutputStream使用getPrivateMethod,所以这些方法不得不被声明为priate以至于供ObjectOutputStream来使用。
在两个方法的开始处,你会发现调用了defaultWriteObject()和defaultReadObject()。它们做的是默认的序列化进程,就像写/读所有的non-transient和 non-static字段(但他们不会去做serialVersionUID的检查).通常说来,所有我们想要自己处理的字段都应该声明为transient。这样的话,defaultWriteObject/defaultReadObject便可以专注于其余字段,而我们则可为这些特定的字段(译者:指transient)定制序列化。使用那两个默认的方法并不是强制的,而是给予了处理复杂应用时更多的灵活性。
你可以从
这里或
这里读到更多有关于序列化的知识。
自己再补充一些:
1.Write的顺序和read的顺序需要对应,譬如有多个字段都用wirteInt一一写入流中,那么readInt需要按照顺序将其赋值;
2.Externalizable,该接口是继承于Serializable ,所以实现序列化有两种方式。区别在于Externalizable多声明了两个方法readExternal和writeExternal,子类必须实现二者。Serializable是内建支持的也就是直接implement即可,但Externalizable的实现类必须提供readExternal和writeExternal实现。对于Serializable来说,Java自己建立对象图和字段进行对象序列化,可能会占用更多空间。而Externalizable则完全需要程序员自己控制如何写/读,麻烦但可以有效控制序列化的存储的内容。
3.正如Effectvie Java中提到的,序列化就如同另外一个构造函数,只不过是有由stream进行创建的。如果字段有一些条件限制的,特别是非可变的类定义了可变的字段会反序列化可能会有问题。可以在readObject方法中添加条件限制,也可以在readResolve中做。参考56条“保护性的编写readObject”和“提供一个readResolve方法”。
4.当有非常复杂的对象需要提供deep clone时,可以考虑将其声明为可序列化,不过缺点也显而易见,性能开销。
分享到:
相关推荐
Java 序列化是指把 Java 对象转换为字节序列的过程,便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,...
个人理解,序列化和反序列化就是一种压缩和解压的过程。压缩和解压讲究一个速度和大小 2、translate 禁止序列化 3、破坏translate java 和file 、javaXML 都可以通过重写私有readObject和writeObject进行破坏...
Java高级程序设计 第5章 Java序列化机制 5.1 应用场景 5.2 相关知识5.3 实施过程 5.4 拓展知识5.5 拓展训练 5.6 课后小结5.7 课后习题 5.8 上机实训 Java高级程序设计实战教程第五章-Java序列化机制全文共15页,当前...
KryoCocoa 是 Kryo 高性能 Java 序列化框架的 Objective-C 移植版本,兼容 Java 版本的序列化格式。示例代码:Kryo *kryo = [Kryo new]; // ... NSOutputStream *outputStream = [NSOutputStream ...
Kryo 是一个快速高效的Java对象图形序列化框架,主要特点是性能、高效和易用。该项目用来序列化对象到文件、数据库或者网络。示例代码:Kryo kryo = new Kryo(); // ... Output output = new Output(new...
FST fast-serialization 是重新实现的 Java 快速对象序列化的开发包。序列化速度更快(2-10倍)、体积更小,而且兼容 JDK 原生的序列化。要求 JDK 1.7 支持。 Maven: <groupId>de.ruedigermoeller ...
在ObjectInputStream 和ObjectOutputStream的帮助下,我们可以轻松的实现序列化。 只要我们的class 实现了java.io.Serializable接口,就可以利用ObjectOutputStream的writeObject()方法将一个对象序列化;利用...
第三是熟悉对象的序列化和反序列化 作为类的方法来实现下面二个方法 ◦public abstract void writeObject(ObjectOutputStream out); ◦public abstract void readObject(ObjectInputStream in); 要熟悉对文件,...
采用对象序列化的 readObject 方法从文件中恢复对象,并操作学生的选课课表,实现退课操作。 3.打印课程对象信息,采用覆盖定义 toString()方法的方式。 实验步骤 在保持实验三项目中,Course 类,Student 类,...
支持AS3的ByteArray序列化对象的AMF格式编码、解码( readObject、writeObject )。 支持AS3的ByteArray的compress、uncompress压缩算法:DEFLATE、LZIB、LZMA。 支持直接修改AS3的ByteArray字节流内编码的对象。 ...
支持AS3的ByteArray序列化对象的AMF格式编码、解码( readObject、writeObject )。 支持AS3的ByteArray的compress、uncompress压缩算法:DEFLATE、LZIB、LZMA。 支持直接修改AS3的ByteArray字节流内编码的对象。 ...
/// /// JSON反序列化 /// /// </summary> public static T JsonDeserialize(string jsonString) { DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); MemoryStream ms = new ...
事实上,即便不加@preserve指令,Jocky对Java语言特有的一些private级别的方法不进行混淆,譬如,在序列化时有特殊作用的writeObject及readObject方法等。但笔者强烈建议: 针对这些有特殊含义不能够被混淆的 ...
事实上,即便不加@preserve指令,Jocky对Java语言特有的一些private级别的方法不进行混淆,譬如,在序列化时有特殊作用的writeObject及readObject方法等。但笔者强烈建议: 针对这些有特殊含义不...
serialization(序列化、次第讀寫) generics(泛型) polymorphism(多型) 全文提要 泛型技術與 Sun JDK的淵源可追溯自 JDK1.3。但無論 JDK 1.3或 JDK1.4,都只是 以編譯器外掛附件的方式來支援泛型語法,...
Jocky混淆编译器是在Sun JDK中提供的Java编译器(javac)的基础上完成的,修改了其中的代码生成过程,对编译器生成的中间代码进行混淆,最后再生成class文件,这样编译和混淆只需要一个步骤就可以完成。另外可以在源...
Java****堆栈与堆内存: 对于类中的方法,... 为什么瞬态提供了自定义的readObject和writeObject方法,以实现比默认方法更好的序列化工作。 arraylist的创建方式:具有初始容量的公共arraylist。 可比者与比较者之间的
录入输出项目,帮助网友解决问题:1、界面的切换,2、对象序列化问题ObjectInputStream ObjectOutputStream 储存数据用的记事本系列化对象的方法
MinorGC 的过程(复制->清空->互换) ....................................................................................... 24 1:eden、servicorFrom 复制到 ServicorTo,年龄+1.................................