java序列化与反序列化的使用

Posted 夜漫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java序列化与反序列化的使用相关的知识,希望对你有一定的参考价值。


个人博客 地址:http://www.wenhaofan.com/article/20180925214701

1、什么是序列化和反序列化

Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization(反序列化)是一种将这些字节重建成一个对象的过程。


说通俗一点:

    序列化就是将java中的对象(其中包含对象的信息),以文件的信息保存下来。

    反序列化就是将反序列化的文件的信息读取出来,并转换为一个对象。


2、什么情况下需要序列化 

    a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;

    b)当你想用套接字在网络上传送对象的时候;

    c)当你想通过RMI传输对象的时候;

3、如何让对象能够被序列化

    将需要序列化的类实现Serializable接口即可,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以序列化。

4、序列化和反序列化例子

    序列化:当我们想要序列化一个对象,首先要创建一个OutputStream(例如FileOutputStream、ByteArrayOutputStream等字节流,对象的序列化是基于字节的,不能使用例如Reader以及Writer等基于字符流的层级结构),然后将这些OutputStream封装在一个ObjectOutputStream中。这时候,只需要调用writeObject()方法就可以将对象序列化,也就是会生成一个文件。

    反序列化:当我们需要将一个序列化之后的文件反序列化为一个对象,首先要创建一个InputStream(例如FileOutputStream、ByteArrayOutputStream等字节流,理由同上)获得生成后的序列化文件的流,然后将其封装进 ObjectInputStream。这时候,只需要调用readObject();方法,该方法会返回一个为Object类型的对象,该对象就是通过序列化文本生成的对象。


代码如下:

package Serializable;


import java.io.Serializable;


/**

 * 测试中需要用来序列化的类

 * @author fwh

 *

 */

public class Person implements Serializable{

/**

 * serialVersionUID 

 * java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。

 * 在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,

 * 可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

 * 也就是说serialVersionUID可以设定为任意一个类型为long的值,

 * 于此同时接收反序列化的对象的类中的serialVersionUID也必须与序列化的类中的serialVersionUID一致,否则就会出错

 * 

 */

private static final long serialVersionUID = 1L;


String name="张三1";



public String getName() {

return name;

}


public void setName(String name) {

this.name = name;

}


public static long getSerialversionuid() {

return serialVersionUID;

}


@Override

public String toString() {

return "Person [name=" + name + "]";

}

}


实现序列化以及反序列化:

    

package Serializable;


import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;


/**

 * 测试序列化以及反序列化

 * @author fwh

 *

 */

public class  Main{

public static void main(String[] args) {

Person person=new Person();

person.setName("李四");

//调用本类中执行序列化的方法将person对象序列化

serializable(person);

System.out.println("这是序列化之前的对象:"+person);

//调用本类中执行反序列化的方法获得我们之前序列化的person对象

FileInputStream fis = null;

try {

fis = new FileInputStream("obj.out");

//因为返回值为Object所以需要强转

Person p=(Person) deserialization(fis);

//输出获得到的

System.out.println("这是通过反序列化得到的对象:"+p);

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

//如果字节流不为空则关闭

if(fis!=null){

try {

fis.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

/**

 * 执行序列化的方法

 */

public static void serializable(Object obj){

FileOutputStream fos=null;

ObjectOutputStream oos = null;

try {

//序列化只能使用字节流,对象的序列化是基于字节的,不能使用Reader和Writer等字符流

fos = new FileOutputStream("obj.out");

//将输出流封装进使用ObjectOutputStream输出至本地

oos=new ObjectOutputStream(fos);

    oos.writeObject(obj);

       

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

//如果不为空则刷新执行序列化功能的输出流

if(oos!=null){

 try {

oos.flush();

oos.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

    

}

       

}

/**

 * 执行反序列化的方法

 * @param fis 包含文件信息路径的字节输入流

 * @return 通过反序列化得到的对象

 */

public static Object deserialization(FileInputStream fis){

        ObjectInputStream ois = null;

        Object obj=null;

try {

//反序列化只能使用字节流,对象的序列化是基于字节的,不能使用Reader和Writer等字符流

ois = new ObjectInputStream(fis);

obj=ois.readObject();

     

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

//如果流不为空,则关闭

if(ois!=null){

 try {

ois.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

     

return obj;

}

}
















以上是关于java序列化与反序列化的使用的主要内容,如果未能解决你的问题,请参考以下文章

Java序列化与反序列化

Java反序列化漏洞——反射与反序列化基础

Java序列化与反序列化

Java序列化与反序列化

Java序列化与反序列化

Java序列化与反序列化