1.概念
java中的对象是存放在内存中的,当程序运行结束,内存中的对象也会随之被系统回收掉。要想保存对象就得序列化。序列化后的对象,可以保存在文件或上传到服务器。从文件或网络数据流中取出对象,就是反序列化。
2.Serializable
java.io.Serializable
是一个空接口,用来标志对象可以被序列化。这个标志可以被java.io.ObjectOutputStream
和java.io.ObjectInputStream
识别,将对象序列化为二进制字节流或从二进制字节流反序列化为对象实例。
3.注意事项
- 若类的成员变量不需要序列化,可以用
transient
修饰,如:
private transient String name;
- 静态变量和
transient
修饰的变量不能被序列化 - 反序列化创建的对象,与原对象数据基本相同,但内存地址不相同,不是同一个对象。需要注意单例对象的反序列化,可能会在内存中产生多个单例对象。可以使用
readResolve()
方法解决,这个方法控制最终反序列化生成的对象。readResolve()
和writeReplace()
不是Object
和Serializable
的方法,是java默认规范的方法
* <p>Serializable classes that need to designate an alternative object to be
* used when writing an object to the stream should implement this
* special method with the exact signature:
*
* <PRE>
* ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
* </PRE><p>
*
* This writeReplace method is invoked by serialization if the method
* exists and it would be accessible from a method defined within the
* class of the object being serialized. Thus, the method can have private,
* protected and package-private access. Subclass access to this method
* follows java accessibility rules. <p>
*
* Classes that need to designate a replacement when an instance of it
* is read from the stream should implement this special method with the
* exact signature.
*
* <PRE>
* ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
* </PRE><p>
- 如果想对某些成员变量做特殊处理,比如取值范围校验、加密数据,可以通过
writeObject()
和readObject()
进行。同样的这两个方法也不是Object
和Serializable
的方法
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
* signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
* throws IOException
* private void readObject(java.io.ObjectInputStream in)
* throws IOException, ClassNotFoundException;
* private void readObjectNoData()
* throws ObjectStreamException;
* </PRE>
*
* <p>The writeObject method is responsible for writing the state of the
* object for its particular class so that the corresponding
* readObject method can restore it. The default mechanism for saving
* the Object's fields can be invoked by calling
* out.defaultWriteObject. The method does not need to concern
* itself with the state belonging to its superclasses or subclasses.
* State is saved by writing the individual fields to the
* ObjectOutputStream using the writeObject method or by using the
* methods for primitive data types supported by DataOutput.
*
* <p>The readObject method is responsible for reading from the stream and
* restoring the classes fields. It may call in.defaultReadObject to invoke
* the default mechanism for restoring the object's non-static and
* non-transient fields. The defaultReadObject method uses information in
* the stream to assign the fields of the object saved in the stream with the
* correspondingly named fields in the current object. This handles the case
* when the class has evolved to add new fields. The method does not need to
* concern itself with the state belonging to its superclasses or subclasses.
* State is saved by writing the individual fields to the
* ObjectOutputStream using the writeObject method or by using the
* methods for primitive data types supported by DataOutput.
*
* <p>The readObjectNoData method is responsible for initializing the state of
* the object for its particular class in the event that the serialization
* stream does not list the given class as a superclass of the object being
* deserialized. This may occur in cases where the receiving party uses a
* different version of the deserialized instance's class than the sending
* party, and the receiver's version extends classes that are not extended by
* the sender's version. This may also occur if the serialization stream has
* been tampered; hence, readObjectNoData is useful for initializing
* deserialized objects properly despite a "hostile" or incomplete source
* stream.
-
private static final long serialVersionUID = 5316419709815709313L;
版本id可以直接指定,如果不设置,会根据类的信息动态生成。