java.io.Serializable与java.io.Externalizable的比较
当两个进程在进行远程通信时,无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送,称为对象的序列化;接收方则需要把字节序列再恢复为Java对象,称为对象的反序列化。 只有实现了Serializable和Externalizable接口的类的对象才能被序列化,而Externalizable接口又继承自Serializable接口。下面是序列化和外部化接口代码:
SerializableMyTest
1package serializableTest;
2
3import java.io.FileInputStream;
4import java.io.FileOutputStream;
5import java.io.ObjectInputStream;
6import java.io.ObjectOutputStream;
7import java.io.Serializable;
8import java.util.Date;
9
10public class SerializableMyTest {
11
12 public static void main(String[] args) throws Exception {
13 // TODO Auto-generated method stub
14 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
15 "shit.obj"));
16 Customer customer = new Customer("Gefforey", 23);
17 out.writeObject("Hello,gefforey");
18 out.writeObject(new Date());
19 out.writeObject(customer);
20 out.writeInt(520);
21 out.close();
22
23 System.out.println();
24 ObjectInputStream in = new ObjectInputStream(new FileInputStream(
25 "shit.obj"));
26 System.out.println("obj1=" + (String) in.readObject());
27 System.out.println("obj2=" + (Date) in.readObject());
28 System.out.println("obj3:" + (Customer) in.readObject());
29 System.out.println("obj4=" + in.readInt());
30 in.close();
31 }
32}
33
34class Customer implements Serializable {
35 public String name;
36
37 public int age;
38
39 public Customer(String name, int age) {
40 this.name = name;
41 this.age = age;
42 }
43
44 public String toString() {
45 return "name=" + name + ",age=" + age + ".";
46 }
47}
48
obj1=Hello,gefforey
1package serializableTest;
2
3import java.io.FileInputStream;
4import java.io.FileOutputStream;
5import java.io.ObjectInputStream;
6import java.io.ObjectOutputStream;
7import java.io.Serializable;
8import java.util.Date;
9
10public class SerializableMyTest {
11
12 public static void main(String[] args) throws Exception {
13 // TODO Auto-generated method stub
14 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
15 "shit.obj"));
16 Customer customer = new Customer("Gefforey", 23);
17 out.writeObject("Hello,gefforey");
18 out.writeObject(new Date());
19 out.writeObject(customer);
20 out.writeInt(520);
21 out.close();
22
23 System.out.println();
24 ObjectInputStream in = new ObjectInputStream(new FileInputStream(
25 "shit.obj"));
26 System.out.println("obj1=" + (String) in.readObject());
27 System.out.println("obj2=" + (Date) in.readObject());
28 System.out.println("obj3:" + (Customer) in.readObject());
29 System.out.println("obj4=" + in.readInt());
30 in.close();
31 }
32}
33
34class Customer implements Serializable {
35 public String name;
36
37 public int age;
38
39 public Customer(String name, int age) {
40 this.name = name;
41 this.age = age;
42 }
43
44 public String toString() {
45 return "name=" + name + ",age=" + age + ".";
46 }
47}
48
obj2=Sat Jun 20 17:32:20 CST 2009
obj3:name=Gefforey,age=23.
obj4=520
AppTest
1package serializableTest;
2
3import java.io.Externalizable;
4import java.io.FileInputStream;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.ObjectInput;
8import java.io.ObjectInputStream;
9import java.io.ObjectOutput;
10import java.io.ObjectOutputStream;
11import java.io.Serializable;
12
13
14//必须得实现Serializable接口
15//writing aborted; java.io.NotSerializableException: serializableTest.Customer2
16class Customer2 implements Serializable {
17 public String name;
18
19 public int age;
20
21 @Override
22 public int hashCode() {
23 final int PRIME = 31;
24 int result = 1;
25 result = PRIME * result + age;
26 result = PRIME * result + ((name == null) ? 0 : name.hashCode());
27 return result;
28 }
29
30 @Override
31 public boolean equals(Object obj) {
32 if (this == obj)
33 return true;
34 if (obj == null)
35 return false;
36 if (getClass() != obj.getClass())
37 return false;
38 final Customer2 other = (Customer2) obj;
39 if (age != other.age)
40 return false;
41 if (name == null) {
42 if (other.name != null)
43 return false;
44 } else if (!name.equals(other.name))
45 return false;
46 return true;
47 }
48
49 public Customer2(String name, int age) {
50 this.name = name;
51 this.age = age;
52 }
53
54 public String toString() {
55 return "name=" + name + ",age=" + age + ".";
56 }
57}
58
59
60/**//*
61 * 相当于要序列化得类
62 */
63class Customer3 implements Externalizable { // Test类必须实现Externalizable接口
64 private String letterstates = "gefforey";
65
66 private int num = 0;
67
68 //要序列化得类中还可以加需要序列化的类,Customer2也要实现Serilizable接口
69 private Customer2 cus =new Customer2("ffffffffff",24);
70
71 public Customer3() {
72 }
73
74 public void writeExternal(ObjectOutput out) throws IOException {
75 out.writeObject(letterstates);
76 out.write(88); // 在序列化的数据最后加个88
77 out.writeObject(cus);
78 System.out.println("in writeExternal---"+cus.hashCode());
79 }
80
81 public void readExternal(ObjectInput in) throws IOException,
82 ClassNotFoundException {
83 letterstates = (String) in.readObject();
84 num = in.read(); // 把数字88加进来
85 Customer2 cusTemp = (Customer2) in.readObject();
86 System.out.println("cus==cusTemp---"+(cus==cusTemp));
87 System.out.println("in readExternal---"+cus.hashCode());
88
89 }
90
91 public void printOut() { // 测试
92 System.out.println(letterstates +"--"+num);
93 }
94}
95
96public class AppTest {
97 private void saveGame() {
98 Customer3 m = new Customer3();
99 if (m != null) {
100 try {
101 FileOutputStream ostream = new FileOutputStream("t.txt");
102 ObjectOutputStream p = new ObjectOutputStream(ostream);
103
104 p.writeObject(m); // writeExternal()自动执行
105
106 p.flush();
107 ostream.close();
108 } catch (IOException ioe) {
109 System.out.println("Error saving file:");
110 System.out.println(ioe.getMessage());
111 }
112 }
113 }
114
115 private void loadGame() {
116 try {
117 FileInputStream instream = new FileInputStream("t.txt");
118 ObjectInputStream p = new ObjectInputStream(instream);
119 Customer3 m = (Customer3) p.readObject();// readExternal()自动执行
120 m.printOut();
121 instream.close();
122 } catch (Exception e) {
123 System.out.println("Error loading file:");
124 System.out.println(e.getMessage());
125 }
126 }
127
128 public static void main(String[] args) {
129 new AppTest().saveGame();
130 new AppTest().loadGame();
131 }
132}
133
in writeExternal----1524332777
1package serializableTest;
2
3import java.io.Externalizable;
4import java.io.FileInputStream;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.ObjectInput;
8import java.io.ObjectInputStream;
9import java.io.ObjectOutput;
10import java.io.ObjectOutputStream;
11import java.io.Serializable;
12
13
14//必须得实现Serializable接口
15//writing aborted; java.io.NotSerializableException: serializableTest.Customer2
16class Customer2 implements Serializable {
17 public String name;
18
19 public int age;
20
21 @Override
22 public int hashCode() {
23 final int PRIME = 31;
24 int result = 1;
25 result = PRIME * result + age;
26 result = PRIME * result + ((name == null) ? 0 : name.hashCode());
27 return result;
28 }
29
30 @Override
31 public boolean equals(Object obj) {
32 if (this == obj)
33 return true;
34 if (obj == null)
35 return false;
36 if (getClass() != obj.getClass())
37 return false;
38 final Customer2 other = (Customer2) obj;
39 if (age != other.age)
40 return false;
41 if (name == null) {
42 if (other.name != null)
43 return false;
44 } else if (!name.equals(other.name))
45 return false;
46 return true;
47 }
48
49 public Customer2(String name, int age) {
50 this.name = name;
51 this.age = age;
52 }
53
54 public String toString() {
55 return "name=" + name + ",age=" + age + ".";
56 }
57}
58
59
60/**//*
61 * 相当于要序列化得类
62 */
63class Customer3 implements Externalizable { // Test类必须实现Externalizable接口
64 private String letterstates = "gefforey";
65
66 private int num = 0;
67
68 //要序列化得类中还可以加需要序列化的类,Customer2也要实现Serilizable接口
69 private Customer2 cus =new Customer2("ffffffffff",24);
70
71 public Customer3() {
72 }
73
74 public void writeExternal(ObjectOutput out) throws IOException {
75 out.writeObject(letterstates);
76 out.write(88); // 在序列化的数据最后加个88
77 out.writeObject(cus);
78 System.out.println("in writeExternal---"+cus.hashCode());
79 }
80
81 public void readExternal(ObjectInput in) throws IOException,
82 ClassNotFoundException {
83 letterstates = (String) in.readObject();
84 num = in.read(); // 把数字88加进来
85 Customer2 cusTemp = (Customer2) in.readObject();
86 System.out.println("cus==cusTemp---"+(cus==cusTemp));
87 System.out.println("in readExternal---"+cus.hashCode());
88
89 }
90
91 public void printOut() { // 测试
92 System.out.println(letterstates +"--"+num);
93 }
94}
95
96public class AppTest {
97 private void saveGame() {
98 Customer3 m = new Customer3();
99 if (m != null) {
100 try {
101 FileOutputStream ostream = new FileOutputStream("t.txt");
102 ObjectOutputStream p = new ObjectOutputStream(ostream);
103
104 p.writeObject(m); // writeExternal()自动执行
105
106 p.flush();
107 ostream.close();
108 } catch (IOException ioe) {
109 System.out.println("Error saving file:");
110 System.out.println(ioe.getMessage());
111 }
112 }
113 }
114
115 private void loadGame() {
116 try {
117 FileInputStream instream = new FileInputStream("t.txt");
118 ObjectInputStream p = new ObjectInputStream(instream);
119 Customer3 m = (Customer3) p.readObject();// readExternal()自动执行
120 m.printOut();
121 instream.close();
122 } catch (Exception e) {
123 System.out.println("Error loading file:");
124 System.out.println(e.getMessage());
125 }
126 }
127
128 public static void main(String[] args) {
129 new AppTest().saveGame();
130 new AppTest().loadGame();
131 }
132}
133
cus==cusTemp---false
in readExternal----1524332777
gefforey--88
序列化会自动存储必要的信息,用以反序列化被存储的实例,而外部化则只保存被存储的类的标识。当你通过java.io.Serializable接口序列化一个对象时,有关类的信息,比如它的属性和这些属性的类型,都与实例数据一起被存储起来。在选择走Externalizable这条路时,Java 只存储有关每个被存储类型的非常少的信息。
每个接口的优点和缺点
Serializable接口
· 优点:内建支持
· 优点:易于实现
· 缺点:占用空间过大
· 缺点:由于额外的开销导致速度变比较慢
Externalizable接口
· 优点:开销较少(程序员决定存储什么)
· 优点:可能的速度提升
· 缺点:虚拟机不提供任何帮助,也就是说所有的工作都落到了开发人员的肩上。
在两者之间如何选择要根据应用程序的需求来定。Serializable通常是最简单的解决方案,但是它可能会导致出现不可接受的性能问题或空间问题;在出现这些问题的情况下,Externalizable可能是一条可行之路。