package com.company;
import java.io.*;
/*
为什么要序列化:
它是处理对象流的一种机制,即可以很方便的保存内存中java对象的状态,同时也为了方便传输。
序列化有什么作用
1.方便传输,速度快,还很安全,被调用方序列化,调用方反序列化即可拿到传输前最原始的java对象,常用于不同进程之间的对象传输
2.方便存储,不管是存储成文件还是数据库,都行,存储为文件,下回要用可以直接反序列拿到对象
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。
请注意,一个类的对象要想序列化成功,必须满足两个条件:
该类必须实现 java.io.Serializable 接口。
该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable接口。
反序列化对象
这里要注意以下要点:
readObject() 方法中的 try/catch代码块尝试捕获 ClassNotFoundException 异常。对于 JVM 可以反序列化对象,它必须是能够找到字节码的类。如果JVM在反序列化对象的过程中找不到该类,则抛出一个 ClassNotFoundException 异常。
注意,readObject() 方法的返回值被转化成 Employee 引用。
当对象被序列化时,属性 SSN 的值为 111222333,但是因为该属性是短暂的,该值没有被发送到输出流。所以反序列化后 Employee 对象的 SSN 属性为 0。
对于一个实体类,不想将所有的属性都进行序列化,有专门的关键字 transient:
private transient String name;
当对该类序列化时,会自动忽略被 transient 修饰的属性。
序列化流与反序列化流
ObjectOutputStream是序列化流,可以将Java程序中的对象写到文件中。
ObjectOutputStream(OutputStream out):参数要传递字节输出流。
void writeObject(Object obj): 向文件中写对象。
ObjectOutputStream 的使用步骤:
创建序列化流,用来写。
调用 writeObject 方法,写对象。
释放资源。
public class Demo01ObjectOutputStream {
public static void main(String[] args) throws IOException {
//1. 创建序列化流,用来写
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day12\\file03-obj.txt"));
//2. 调用writeObject方法,写对象
Person p = new Person("张三丰", 100);
oos.writeObject(p);
//3. 释放资源。
oos.close();
}
}
ObjectInputStream 是反序列化流, 可以将文件中的对象读取到 Java 程序中。
ObjectInputStream(InputStream in):参数要传递字节输入流。
Object readObject(): 从文件中读取对象,并将该对象返回。
反序列化流的使用步骤:
创建 ObjectInputStream 反序列化流。
调用 readObject 方法,读取对象。
释放资源。
tips:调用 readObject 方法读取对象时,对象所对应的类不存在,那么会报错(ClassNotFoundException)
被 static 修饰的成员变量无法序列化,无法写到文件。
如果不希望某个成员变量写到文件,同时又不希望使用 static 关键字, 那么可以使用 transient。transient 关键字表示瞬态,被 transient 修饰的成员变量无法被序列化。
public class Demo03StaticAndTransient {
public static void main(String[] args) throws IOException, ClassNotFoundException {
writePerson();
readPerson();
}
//从文件中读取Person对象
public static void readPerson() throws IOException, ClassNotFoundException {
//创建反序列化流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day12\\file04-obj.txt"));
//从文件中读取对象
Object obj = ois.readObject();
System.out.println(obj);
//释放资源
ois.close();
}
//向文件中写Person对象
public static void writePerson() throws IOException {
//创建序列化流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day12\\file04-obj.txt"));
//向文件中写Person对象
oos.writeObject(new Person("张三丰", 100));
//关流
oos.close();
}
}
*/
class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " " + address);
}
}
public class Serializables {
public static void main(String[] args) {
//序列化
Employee e = new Employee();
e.name = "小明";
e.address = "三号胡同";
e.SSN = 112223344;
e.number = 111;
try {
FileOutputStream fileOut = new FileOutputStream("employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
} catch (IOException i) {
i.printStackTrace();
}
//反序列化
Employee ee = null;
try {
FileInputStream fileInV1 = new FileInputStream("employee.ser");
ObjectInputStream inV1 = new ObjectInputStream(fileInV1);
ee = (Employee) inV1.readObject();
inV1.close();
fileInV1.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + ee.name);
System.out.println("Address: " + ee.address);
System.out.println("SSN: " + ee.SSN);
System.out.println("Number: " + ee.number);
}
}
网友评论