Java中的序列化

什么是Java对象序列化?

Java中的序列化主要是指对Java对象的序列化。Java对象的序列化就是把Java对象转换成跟平台无关的二进制流,反序列化就是把序列化的二进制流恢复成原来的JAVA对象。

为什么要进行序列化?

当虚拟机停止运行之后,内存中的对象就会消失,Java对象经过序列化可以将对象转换成二进制流保存下来,比如保存在磁盘中,一般是保存到文件中,或者将对象的序列化为字符串保存到数据库中,然后在需要读取对象情况的时候反序列化为对象。可以对序列化后的对象进行读写操作。

java对象进行远程传输的时候需要序列化,对象序列化之后可以将通过流的方式在网络上传输。

怎样实现对象的序列化?

被序列化的类需要首先实现Serializable接口,然后再使用ObjectOutputStream对象输出流的writeObject(Object obj)方法将参数obj的对象序列化写出,把得到的字节序列写到一个目标输出流中;使用ObjectIntputStream对象输入流的readObject( )方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

序列化的时候需要注意什么?

这里有几个原则,我们一起来看下:

1、Serializable接口是一个标示性接口,接口中没有定义任何的方法或字段,因此没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。

2、静态变量和成员方法不可序列化,就是只对对象的状态进行保存,而不管对象的方法。

3、当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

3、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;前提是该类中的所有引用对象也必须是可以被序列化的。否则整个序列化操作将会失败,并且会抛出一个NotSerializableException,除非我们将不可序列化的引用标记为transient。

4、声明成transient的变量不被序列化工具存储,同样,static变量也不被存储。因为static代表类的状态,transient代表对象的临时数据。因此如果某个属性不需要被序列化,可以添加transient关键字,在序列化对象的时候就不会对这个属性进行序列化了。

Java有哪些对象序列化的方式?

Java序列化对象的方式主要有原生的以流的方法进行的序列化、Json序列化和FastJson序列化。

不管使用哪种序列化方法被序列化的对象都必须实现Serializable接口。

(1)Java原生序列化

Java原生序列化方法即通过Java原生流(ObjectInputStream和ObjectOutputStream之间的转化)的方式进行的序列化。在序列化之前JavaBean实体类必须实现Serializable接口,否则无法序列化。

Java原生序列化代码示例如下:

首先定义一个Student类,实现Serializable接口。

package com.serializable.demo;

import java.io.Serializable;
//Student类用于演示对象的序列化,Student类通过实现Serializable接口拥有了序列化的能力
public class Student implements Serializable{
        private String id;
        private String name;
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
}

编写测试类:

package com.serializable.demo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeIODemo {
    //测试入口
    public static void main(String[] args) throws Exception{
        Student student=new Student();
        student.setId("1");
        student.setName("Lily");
        serializeByIO(student);
    }
    //序列化和反序列化
    public static void serializeByIO(Object obj) throws Exception{
        //序列化
        Long t1 = System.currentTimeMillis();
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
        objOut.writeObject(obj);
        System.out.println("java serialize: " +(System.currentTimeMillis()- t1) + "ms; 总大小:" + byteOut.toByteArray().length );
        //反序列化
        Long t2 = System.currentTimeMillis();
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream objIn = new ObjectInputStream(byteIn);
        Student stu = (Student) objIn.readObject();
        System.out.println("java deserialize: " + (System.currentTimeMillis() - t2) + "ms; Student: stu.getId()=" + stu.getId()+";stu.getName()="+stu.getName());
    }
}

运行结果:

(2)Json序列化

Json序列化一般会使用jackson包,通过ObjectMapper类来进行一些操作,比如将对象转化为byte数组或者将json串转化为对象。现在对数据的传输大都是使用json作为服务器端返回的数据格式。比如调用一个服务器接口,通常的请求为xxx.json?a=xxx&b=xxx的形式。要序列化的对象还是Student类,Json序列化的测试代码如下:

package com.serializable.demo;

import com.fasterxml.jackson.databind.ObjectMapper;

public class SerializeJsonDemo {
    //测试入口
    public static void main(String[] args) throws Exception{
        Student student=new Student();
        student.setId("1");
        student.setName("Lily");
        serializeByJson(student);
    }
    //序列化
    public static void serializeByJson(Object obj) throws Exception{
        ObjectMapper mapper = new ObjectMapper();
        //序列化
        Long t1 = System.currentTimeMillis();
        String writeValueAsString  = mapper.writeValueAsString(obj);
        System.out.println("json serialize: " + (System.currentTimeMillis() - t1) + "ms; writeValueAsString="+writeValueAsString+";总大小:" + writeValueAsString.length());
        //反序列化
        Long t2 = System.currentTimeMillis();
        Student stu = mapper.readValue(writeValueAsString, Student.class);
        System.out.println("json deserialize: " + (System.currentTimeMillis() - t2) + "ms; Student: stu.getId()=" + stu.getId()+";stu.getName()="+stu.getName());
    }

}

运行结果:

 (3)FastJson序列化

fastjson 是阿里巴巴开发的一个性能很好的Java 语言实现的Json解析器和生成器。

特点:速度快,测试表明fastjson具有极快的性能,超越任其他的java json parser。功能强大,支持多种对象格式。无依赖,能够直接运行在Java SE 5.0以上版本。 

使用时候需引入FastJson第三方jar包。要序列化的对象还是Student类,FastJson序列化代码测试如下:

package com.serializable.demo;

import com.alibaba.fastjson.JSON;

public class SerializeFastJsonDemo {
    //测试入口
    public static void main(String[] args) throws Exception{
        Student student=new Student();
        student.setId("1");
        student.setName("Lily");
        serializeByFastJson(student);
    }
    //序列化和反序列化
    public static void serializeByFastJson(Object obj) throws Exception{
        //序列化
        Long t1 = System.currentTimeMillis();
        String text = JSON.toJSONString(obj);
        System.out.println("fastJson serialize: " +(System.currentTimeMillis() - t1) + "ms; text="+text+"; 总大小:" + text.length());
        //反序列化
        Long t2 = System.currentTimeMillis();
        Student stu = JSON.parseObject(text, Student.class);
        System.out.println("json deserialize: " + (System.currentTimeMillis() - t2) + "ms; Student: stu.getId()=" + stu.getId()+";stu.getName()="+stu.getName());
    }

}

可以发现:对于小数量的序列化操作,序列化后对象的所占大小上:json序列化和fastJson序列化所占大小较少的,java原生序列化较多。对于序列化耗时,java原生序列化耗时最少,其次是json,最后是fastJson。 不过这是对小数量的操作,大数据量的操作这三者性能之间的差别可能会与此不同。

参考:几种Java序列化方式的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值