Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。从而达到网络传输、本地存储的效果。
本文主要要看看JDK中使用Serializable和Externalizable接口来完成Java对象序列化,并给出部分属性序列化的几种方式,最终做出Serializable和Externalizable接口的几个方面的对比。
序列化Serializable
要实现Java对象的序列化,只要将类实现Serializable或Externalizable接口即可。
采用类实现Serializable接口的序列化很简单,Java自动会将非transient修饰属性序列化到指定文件中去。
举个例子:
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);
}
}
一个简单的示例,就完成了Book对象的序列化和反序列化。
在上述示例中,Book对象中的所有的属性都被序列化。如果里面存在部分属性,我们不想要被序列化,该如何做呢?
部分属性序列化
如果只想将部分属性进行序列化,可以采用如下几种方法:
- 使用transient关键字
- 添加writeObject和readObject方法
- 使用Externalizable实现
使用transient关键字
对属性添加transient关键字,可以防止该属性序列化~
如下示例中,我们不想isbn和authors属性被序列,添加上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;
... ...
}
运行上述提到的SerializableTest.java程序,输出如下结果,我们可以看出isbn和authors的值都为null,表明这两个属性没有被序列化~
book==>Book [name=Hello Java, isbn=ABC123456789, authors=[John, Eric]] deserializedBook==>Book [name=Hello Java, isbn=null, authors=null]
添加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();
}
... ...
}