用法
- Externalizalbe拓展了Serializable接口,Serializable接口更类似一个标记,没有方法,而Externalizable需要重写writeExternal 和 readExternal方法
- 可以序列化的对象包括:基本数据类型、所有的集合类以及其他class对象
- 对象序列化不仅是该对象,还包括内含的所有对象
序列化的步骤
- 创建
OutputStream对象:OutputStream outputStream = new FileOutputStream("output.txt") - 封装到
ObjectOutputStream对象中:ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream) - 调用writeObject 方法实现序列化:
objectOutputStream.writeObject(Object) - 最后记得关闭资源:
objectOutputStream.close(),outputStream .close()
反序列化的步骤
- 首先要创建OutputStream对象:
InputStream inputStream= new FileInputStream("output.txt") - 将其封装到ObjectInputStream对象内:
ObjectInputStream objectInputStream= new ObjectInputStream(inputStream); - 调用
readObject()即可完成对象的反序列化:objectInputStream.readObject(); - 最后关闭资源:
objectInputStream.close(),inputStream.close();
用法实例
讲解
- 创建了一个User类,有
username和password的属性,实现了Serializable的接口
package main.java.dai.model;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- 创建了一个Gamer类,有User、name、age的属性,实现了
Serializable的接口
package main.java.dai.model;
import java.io.Serializable;
public class Gamer implements Serializable {
private static final long serialVersionUID = 1L;
private User user;
private String name;
private transient int age;
public Gamer(User user, String name, int age) {
this.user = user;
this.name = name;
this.age = age;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- 创建了一个Man类,有name、age的属性,实现了Externalizable的接口,重写了
writeExternal和readExternal的方法
package main.java.dai;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Man implements Externalizable {
private String name;
private int age;
public Man() {
System.out.println("man constructor");
}
public Man(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("write external");
out.writeObject(name);
out.writeObject(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
System.out.println("read external");
name = (String) in.readObject();
age = in.readInt();
}
}
- 创建了主函数,用作测试,分别有
writeSerivalizableObject、readSerializableObject、writeExternalizableObject、readExternalizableObject的方法
package main.java.dai;
import main.java.dai.model.Gamer;
import main.java.dai.model.User;
import java.io.*;
public class Main {
public static void main(String[] args) {
System.out.println("Serivalizable demo:");
writeSerivalizableObject();
readSerializableObject();
System.out.println("Externalizable demo:");
writeExternalizableObject();
readExternalizableObject();
}
public static void writeSerivalizableObject() {
try {
User user = new User("daiyuanli", "123456");
Gamer gamer = new Gamer(user, "代元丽", 20);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt"));//使用匿名函数之后不必close
objectOutputStream.writeObject("string");//试试序列化String类型
objectOutputStream.writeObject(gamer);//序列化gamer的同时也会序列化user
objectOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readSerializableObject(){
try{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt"));
String string =(String) objectInputStream.readObject();
Gamer gamer = (Gamer) objectInputStream.readObject();
objectInputStream.close();
System.out.println("String"+string+",name:"+gamer.getName()+",age:"+gamer.getAge()+",User = [ usernam:"+gamer.getUser().getUsername()+",password:"+gamer.getUser().getPassword()+"]");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void writeExternalizableObject(){
Man man = new Man("张山",22);
try{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("externalizable.txt"));
objectOutputStream.writeObject(man);
objectOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readExternalizableObject(){
try{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("externalizable.txt"));
Man man = (Man) objectInputStream.readObject();
objectInputStream.close();
System.out.println("name:"+man.getName()+",age:"+man.getAge());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出结果
Stringstring,name:代元丽,age:0,User = [ usernam:daiyuanli,password:123456]
Externalizable demo:
write external
man constructor
name:张山,age:22
异同
-
序列化责任:
当类实现
Serializable的接口时,Jvm完全负责序列化,而使用Externalizable的情况下,程序员负责整个序列化和反序列化过程 -
用法:
序列化一整个对象时,例如上例中的
gamer,使用Serialzable接口更适合,而自定义序列化,使用Externalizable可以控制流程 -
性能:
Serializable接口使用反射和元数据,相对较慢的性能
-
自定义序列化:
实现
Serializable接口的类使用transient关键字可以保证在序列化对象的过程中,该属性不被序列化,但JVM仍会将该字段的默认值加载进文件中








网友评论