Externalizable vs Serializable
Externalizable和Serializable的一些比较点,如下:
【1】 Serializable 是标识接口
public interface Serializable {
}
public interface Externalizable extends java.io.Serializable {
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
Externalizable 接口继承于Serializable,实现该接口,需要重写readExternal和writeExternal方法~
【2】Serializable提供了两种方式进行对象的序列化,
- 采用默认序列化方式,将非transatient和非static的属性进行序列化
- 编写readObject和writeObject完成部分属性的序列化
Externalizable 接口的序列化,需要重写writeExternal和readExternal方法,并且在方法中编写相关的逻辑完成序列化和反序列化。
【3】Externalizable接口的实现方式一定要有默认的无参构造函数~
- 如果,没有无参构造函数,反序列化会报错~ 验证一下~ Book添加一个有参数的Book构造函数~
- Serializable接口实现,其采用反射机制完成内容恢复,没有一定要有无参构造函数的限制~
【4】采用Externalizable无需产生序列化ID(serialVersionUID)~而Serializable接口则需要~
【5】相比较Serializable, Externalizable序列化、反序列更加快速,占用相比较小的内存
在项目中,大部分的类还是推荐使用Serializable, 有些类可以使用Externalizable接口,如:
- 完全控制序列的流程和逻辑
- 需要大量的序列化和反序列化操作,而你比较关注资源和性能~ 当然,这种情况下,我们一般还会考虑第三方序列化/反序列化工具,如protobuf等进行序列化和反序列化操作~
API的说明
Externalizabl:
Serializable
DEMO
import java.io.Serializable;
import java.util.List;
/**
* @Type Book.java
* @Desc
* @author wangmengjun
* @date 2017年12月1日 下午7:16:29
* @version
*/
public class Book implements Serializable {
private static final long serialVersionUID = -6212470156629515269L;
/**书名*/
private String name;
/**ISBN*/
private String isbn;
/**作者*/
private List<String> authors;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the isbn
*/
public String getIsbn() {
return isbn;
}
/**
* @param isbn the isbn to set
*/
public void setIsbn(String isbn) {
this.isbn = isbn;
}
/**
* @return the authors
*/
public List<String> getAuthors() {
return authors;
}
/**
* @param authors the authors to set
*/
public void setAuthors(List<String> authors) {
this.authors = authors;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Book [name=" + name + ", isbn=" + isbn + ", authors=" + authors + "]";
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @Type SerializationUtil.java
* @Desc
* @author wangmengjun
* @date 2017年12月1日 下午7:23:04
* @version
*/
public class SerializationUtil {
/**
* 从一个给定的文件完成反序列化
*/
public static Object deserialize(String fileName) throws IOException,
ClassNotFoundException {
FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(bis);
Object obj = ois.readObject();
ois.close();
return obj;
}
/**
* 将给定的对象序列化到指定的文件中去
*/
public static void serialize(Object obj, String fileName)
throws IOException {
FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.close();
}
}
public class SerializableTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Book book = new Book();
book.setIsbn("ABC123456789");
book.setName("Hello Java");
book.setAuthors(Arrays.asList("John","Eric"));
//book==>Book [name=Hello Java, isbn=ABC123456789, authors=[John, Eric]]
System.out.println("book==>" + book);
/**
* 将book对象序列化到book.temp文件中去
*/
String fileName = "book.temp";
SerializationUtil.serialize(book, fileName);
/**
* 从book.temp文件中,反序列化一个Book对象
*/
Book deserializedBook = (Book) SerializationUtil.deserialize(fileName);
//deserializedBook==>Book [name=Hello Java, isbn=ABC123456789, authors=[John, Eric]]
System.out.println("deserializedBook==>" + deserializedBook);
}
}
部分属性序列化
如果只想将部分属性进行序列化,可以采用如下几种方法:
1、 使用transient关键字
2、 添加writeObject和readObject方法
3、 使用Externalizable实现
使用transient关键字
public class Book implements Serializable {
private static final long serialVersionUID = -6212470156629515269L;
/** 书名 */
private String name;
/** ISBN */
private transient String isbn;
/** 作者 */
private transient List<String> authors;
... ...
}
重写writeObject和readObject方法
另外,我们也可以采用编写私有方法writeObject和readObject,完成部分属性的序列化。修改Book类,增加writeObject 和 readObject方法,如:
public class Book implements Serializable {
private static final long serialVersionUID = -6212470156629515269L;
/** 书名 */
private String name;
/** ISBN */
private String isbn;
/** 作者 */
private List<String> authors;
private void writeObject(ObjectOutputStream oos) throws IOException {
// oos.defaultWriteObject();
oos.writeObject(name);
oos.writeObject(isbn);
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// ois.defaultReadObject();
name = (String) ois.readObject();
isbn = (String) ois.readObject();
}
... ...
}
使用Externalizable实现
还有一种方式,就是使用Externalizable完成部分属性的序列化。
Externalizable继承自Serializable,使用Externalizable接口需要实现writeExternal以及readExternal方法~在writeExternal方法中,写入想要外部序列化的元素~
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.List;
/**
* @Type Book.java
* @Desc
* @author wangmengjun
* @date 2017年12月1日 下午7:16:29
* @version
*/
public class Book implements Externalizable {
/** 书名 */
private String name;
/** ISBN */
private String isbn;
/** 作者 */
private List<String> authors;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeObject(isbn);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
isbn = (String) in.readObject();
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the isbn
*/
public String getIsbn() {
return isbn;
}
/**
* @param isbn
* the isbn to set
*/
public void setIsbn(String isbn) {
this.isbn = isbn;
}
/**
* @return the authors
*/
public List<String> getAuthors() {
return authors;
}
/**
* @param authors
* the authors to set
*/
public void setAuthors(List<String> authors) {
this.authors = authors;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Book [name=" + name + ", isbn=" + isbn + ", authors=" + authors + "]";
}
}