对象序列化基本概念
序列化的基本定义:将内存保存的数据以二进制数据流的形式进行处理,可以实现对象的保存或者网络传输。
而对象序列化一般都是计算机处理的,用户只做标记。
并不是所有对象都可以进行序列化,强制性要求:需要序列化的类需要实现java.io.Serializable接口,作为序列化标记。
Serializable接口没有方法,他描述的是类的能力。
范例:定义一个可以序列化的类
@SuppressWarnings("serial")
class Person implements Serializable{
private String name;
private int age;
public Person(String name,int age) {
this.name=name;
this.age=age;
}
public String toString() {
return "名字:"+name+",年龄:"+age;
}
}
此时Person类产生的对象都可以进行二进制传输,属于可以被序列化的程序类。
序列化与反序列化处理
有了序列化的支持类之后,如果想要实现序列化和反序列化的操作可以使用两个类:
- 序列化:
ObjectOutputStream
- 类定义:
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants
- 构造方法:
public ObjectOutputStream(OutputStream out) throws IOException
- 操作方法1:
public final void writeObject (Object obj) throws IOException
- 类定义:
- 反序列化:
ObjectInputStream
- 类定义:
public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
- 构造方法:
public ObjectInputStream(InputStream in) throws IOException
- 操作方法1:
public final Object readObject()throws IOException,FileNotFoundException
- 类定义:
范例:实现序列化与反序列化
import java.io.*;
public class SerializeTest {
private static final File SAVE_FILE=new File("F:\\course\\Person");
public static void main(String[] args) throws Exception {
saveDate(new Person("妹妹",18));
System.out.println(printDate());
}
public static void saveDate(Object obj) throws Exception {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oos.writeObject(obj);//序列化
oos.close();
}
public static Object printDate() throws Exception {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj=ois.readObject();//反序列化
ois.close();
return obj;
}
}
@SuppressWarnings("serial")
class Person implements Serializable{
private String name;
private int age;
public Person(String name,int age) {
this.name=name;
this.age=age;
}
public String toString() {
return "名字:"+name+",年龄:"+age;
}
}
java中序列化和反序列化必须使用内部提供的对象操作流,因为这里牵扯到二进制数据格式,所以不能自定义处理。如果想要使用一组对象序列化可以使用对象数组。
在开发过程中很少见到ObjectOutputStream,ObjectInputStream。会有一些容器帮助实现。更多关注Serializable接口。
transient关键字
默认情况下,当执行对象序列化时会将所有属性全部进行序列化处理。如果某些属性不需要序列化处理可以使用transient关键字进行标记。
public transient String name;
此时name属性的内容是不会被保存下来的。换言之,读取的数据name是其对应数据类型的默认值(null)。
使用场景:如果类中有一些需要计算保存的属性内容,往往就不需要序列化。(例:单价,数量,总价)。(但开发过程中需要被序列化的类大多是简单java类,所以很少使用。)