javaIO流(五)--对象序列化
一.序列化概念
几乎只要是我们的java开发,就一定会存在有序列化的概念,而正是有序列化的概念逐步发展,慢慢也有了更多的系列化的标准.
--所谓的对象序列化指的是将内存中保存的对象,以二进制数据流的形式进行处理,可以实现对象的保存或网络传输.我们首先需要知道所谓的对象都是处在堆内存当中的(每一块堆内存中描述的就是我们所说的真正的对象),我们所需要做的就是将内存中的数据保存为文件或者发送到远程的服务器上,这样所有的客户都可以获取到我的对象,也可以将是数据保存到数据库中,在需要的时候进行数据的读取.
--然而并不是所有的对象都可以被序列化,在java中有一个强制性的要求:如果要序列化对象,那么对象所在的类一定要实现java.io.Serializable(JDK1.1)父接口,作为我们序列化的标记.我们可以发现这个接口是一个空接口,因为它描述的是一种类的能力.
--范例:定义一个可以被序列化的类
1 class Person implements Serializable { //这样就表示这个类可以被序列化
2 private String name;
3 private int age;
4 public Person(String name, int age) {
5 this.name = name;
6 this.age = age;
7 }
8
9 public String getName() {
10 return name;
11 }
12
13 public void setName(String name) {
14 this.name = name;
15 }
16
17 public int getAge() {
18 return age;
19 }
20
21 public void setAge(int age) {
22 this.age = age;
23 }
24
25 @Override
26 public String toString() {
27 return "Person{" +
28 "name='" + name + '\'' +
29 ", age=" + age +
30 '}';
31 }
32 }
--此时Person类产生的每一个对象都可以实现二进制的数据传输,属于可以被序列化的程序类
二.序列化与反序列化
有了序列化的支持类之后,如果要实现序列化和反序列化的操作就可以实现利用以下两个类完成:
--序列化与反序列化支持类:
序列化:ObjectOutputStream(JDK1.1) public final void writeObject(Object obj) throws IOException
反序列化:ObjectInputStream(JDK1.1) public final Object readObject()throws IOException, ClassNotFoundException
--范例:实现序列化:
1 package IO常用类库.对象序列化;
2
3 import java.io.*;
4
5 /**
6 * @author : S K Y
7 * @version :0.0.1
8 */
9 class Person implements Serializable { //这样就表示这个类可以被序列化
10 private String name;
11 private int age;
12
13 public Person(String name, int age) {
14 this.name = name;
15 this.age = age;
16 }
17
18 public String getName() {
19 return name;
20 }
21
22 public void setName(String name) {
23 this.name = name;
24 }
25
26 public int getAge() {
27 return age;
28 }
29
30 public void setAge(int age) {
31 this.age = age;
32 }
33
34 @Override
35 public String toString() {
36 return "Person{" +
37 "name='" + name + '\'' +
38 ", age=" + age +
39 '}';
40 }
41 }
42
43 public class SerializableDemo {
44 public static final File SAVE_FILE =
45 new File("D:" + File.separator + "java-test" + File.separator + "person.save");
46
47 public static void main(String[] args) throws IOException, ClassNotFoundException {
48 Person person = new Person("张三", 22);
49 saveObject(person);
50 Person readPerson = (Person) loadObject();
51 System.out.println(readPerson);
52 }
53
54 public static void saveObject(Object obj) throws IOException {
55 if (!SAVE_FILE.getParentFile().exists()) {
56 SAVE_FILE.getParentFile().mkdirs();
57 }
58 ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
59 outputStream.writeObject(obj); //序列化
60 outputStream.close();
61 }
62
63 public static Object loadObject() throws IOException, ClassNotFoundException {
64 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(SAVE_FILE));
65 Object object = inputStream.readObject(); //反序列化
66 inputStream.close();
67 return object;
68 }
69
70 }
--在java中的对象序列化和反序列化必须使用内部提供的对象操作流,因为这里面牵扯到二进制数据的格式,因此无法自定义处理,另外如果要想实现一组对象的序列化,则可以使用对象数组完成,在很多的实际项目的开发之中,开发者很少能够见到这两个类的直接操作,因为会有一些程序类容器帮助开发者自动实现.
三.transient关键字
默认情况下当执行了对象序列化后会将类中的全部属性的内容进行全部的序列化,但是很多情况下有一些属性可能并不需要进行序列化的处理,这个时候就可以在属性定义上使用transient关键字来完成
1 package IO常用类库.对象序列化;
2
3 import java.io.*;
4
5 /**
6 * @author : S K Y
7 * @version :0.0.1
8 */
9 class Person implements Serializable { //这样就表示这个类可以被序列化
10 private transient String name; //在进行序列化处理的时候name属性的内容将不会被保存下来
11 private int age;
12
13 public Person(String name, int age) {
14 this.name = name;
15 this.age = age;
16 }
17
18 public String getName() {
19 return name;
20 }
21
22 public void setName(String name) {
23 this.name = name;
24 }
25
26 public int getAge() {
27 return age;
28 }
29
30 public void setAge(int age) {
31 this.age = age;
32 }
33
34 @Override
35 public String toString() {
36 return "Person{" +
37 "name='" + name + '\'' +
38 ", age=" + age +
39 '}';
40 }
41 }
42
43 public class SerializableDemo {
44 public static final File SAVE_FILE =
45 new File("D:" + File.separator + "java-test" + File.separator + "person.save");
46
47 public static void main(String[] args) throws IOException, ClassNotFoundException {
48 Person person = new Person("张三", 22);
49 saveObject(person);
50 Person readPerson = (Person) loadObject();
51 System.out.println(readPerson);
52 }
53
54 public static void saveObject(Object obj) throws IOException {
55 if (!SAVE_FILE.getParentFile().exists()) {
56 SAVE_FILE.getParentFile().mkdirs();
57 }
58 ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
59 outputStream.writeObject(obj); //序列化
60 outputStream.close();
61 }
62
63 public static Object loadObject() throws IOException, ClassNotFoundException {
64 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(SAVE_FILE));
65 Object object = inputStream.readObject(); //反序列化
66 inputStream.close();
67 return object;
68 }
69
70 }
--如果假设类之中是有一些需要计算保存的属性内容,往往是不需要被序列化的(商品的数量,单价,总价),这个时候就可以使用这个关键字,但是在实际的开发之中,大部分需要被序列化的往往都是简单的java类,所以这个关键字的出现频率并不高