Serializable和Externalizable浅析

 

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对象中的所有的属性都被序列化如果里面存在部分属性,我们不想要被序列化,该如何做呢?

 

部分属性序列化

如果只想将部分属性进行序列化,可以采用如下几种方法:

  1. 使用transient关键字
  2. 添加writeObject和readObject方法
  3. 使用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();
	}

... ...

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值