栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java序列化与反序列化

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java序列化与反序列化

Java序列化与反序列化

1. 序列化与反序列化概述

1.1 序列化与反序列化简介1.2 序列化与反序列化作用1.3 序列化与反序列化工具 2. 常用序列化工具详解

2.1 serialVersionUID2.2 fastjson2.3 Kryo2.4 jackson2.5 gson 2. 代码实现

1. 序列化与反序列化概述 1.1 序列化与反序列化简介

序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

1.2 序列化与反序列化作用

序列化与反序列化的作用就是将内存对象持久化存储或者对象通过网络传输到远端。就是为了对象的存储与传输,对象的系列化更方便对象的存储与传输,另外序列化与反序列化不仅限于Java,这里主要为了说明Java中的序列化与反序列化。

1.3 序列化与反序列化工具

目前JAVA常用的序列化有protobuf,json,xml,Serializable,hessian,kryo。
Serializable:JDK 原生是 Java 自带的序列化框架。

protobuf:谷歌公司出的一款开源项目,转码性能高,支持多语言;

JSON:用途最广泛,序列化方式还衍生了阿里的fastjson,谷歌的GSON,jackson,美团的MSON等更加优秀的转码工具。现在越来越多的网站采用JSON来交换数据,在Json.org网站上,Java可以使用的解析Json的组件就有超过20种。
Json官网:http://json.org/。

Kryo 是一个快速高效的二进制序列化框架,号称是 Java 领域最快的。它的特点是序列化速度快、体积小、接口易使用。

2. 常用序列化工具详解 2.1 serialVersionUID

1.Serializable概念
JDK 原生是 Java 自带的序列化框架,与 Java 语言是强绑定的,通过 JDK 将对象序列化后是无法通过其他语言进行返序列化的,所以它的通用性比较差。Serializable仅仅是一个标识的作用,用来告诉 JVM 这个对象可以被序列化。

2.serialVersionUID的作用
序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。

3.serialVersionUID两种生成方式
一个是默认的1L,比如:private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:

public class ClueResult implements Serializable {
private static final long serialVersionUID = 8196133923301996629L;
private static final long serialVersionUID = 1L;
}

4.serialVersionUID两种生成方式区别
看上去,好像每个类的这个类不同,似乎这个SerialVersionUid在类之间有某种关联。其实不然,两种都可以,从JDK文档也看不出这一点。我们只要保证在同一个类中,不同版本根据兼容需要,是否更改SerialVersionUid即可。

对于第一种serialVersionUID = 1L,需要了解哪些情况是可兼容的,哪些根本就不兼容。 在可兼容的前提下,可以保留旧版本号,如果不兼容,或者想让它不兼容,就手工递增版本号。1->2->3…

第二种方式,是根据类的结构产生的hash值。增减一个属性、方法等,都可能导致这个值产生变化。我想这种方式适用于这样的场景,开发者认为每次修改类后就需要生成新的版本号,不想向下兼容,操作就是删除原有serialVesionUid声明语句,再自动生成一下。

2.2 fastjson

fastjson 是阿里巴巴出品的一款序列化框架,可以将对象序列化为 JSON 字符串,已性能著称,但是性能是以写死代码,一味追求性能忽略代码质量为代价,截止到目前Issues为1.7K,问题很多,使用确实方便。
fastjson github地址:https://github.com/alibaba/fastjson/


    com.alibaba
    fastjson
    1.2.76

2.3 Kryo

Kryo 是一个快速高效的二进制序列化框架,号称是 Java 领域最快的。它的特点是序列化速度快、体积小、接口易使用。
Kryo支持自动深/浅拷贝,它是直接通过对象->对象的深度拷贝,而不是对象->字节->对象的过程。
关于 Kryo 更多的介绍可以去 Github 查看:https://github.com/EsotericSoftware/kryo
关于通用性,Kryo 是一款针对 Java 语言开发的框架,基本很难跨语言使用,因此通用性比较差。


    com.esotericsoftware
    kryo
    5.3.0

2.4 jackson

非常有名的json解析工具jackson。


    com.fasterxml.jackson.core
    jackson-core
    2.9.2

 

    com.fasterxml.jackson.core
    jackson-databind
    2.9.2

 

    com.fasterxml.jackson.core
    jackson-annotations
    2.9.2

2.5 gson

谷歌的json工具GSON。


    com.google.code.gson
    gson
    2.8.2

2. 代码实现

UserDTO

package com.jerry.unit.json;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;


@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO implements Serializable {
    private static final long serialVersionUID = 8196133923301996629L;
    private String name;
    private String age;
    private String phone;
}

JDKSerializationUtil

package com.jerry.unit.json;

import java.io.*;


public class JDKSerializationUtil {
    
    public static byte[] serialize(Object obj) throws IOException {
        // 字节输出流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        // 将对象序列化为二进制字节流
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(obj);
        // 获取二进制字节数组
        byte[] bytes = byteArrayOutputStream.toByteArray();
        //  关闭流
        objectOutputStream.close();
        byteArrayOutputStream.close();
        return bytes;
    }

    
    public static  T deSerialize(byte[] bytes) throws IOException, ClassNotFoundException {
        // 字节输入流
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        // 将二进制字节流反序列化为对象
        final ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        final T object = (T) objectInputStream.readObject();
        // 关闭流
        objectInputStream.close();
        byteArrayInputStream.close();
        return object;
    }
}

KryoSerializationUtil

package com.jerry.unit.json;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;


public class KryoSerializationUtil {
    
    public static byte[] serialize(Object obj, Kryo kryo) {
        Output output = new Output(1024);
        kryo.writeObject(output, obj);
        output.flush();
        return output.toBytes();
    }

    
    public static  T deSerialize(byte[] bytes, Class clazz, Kryo kryo) {
        Input input = new Input(bytes);
        return kryo.readObject(input, clazz);
    }
}

SerializationUtils

package com.jerry.unit.json;

import com.alibaba.fastjson.JSON;
import com.esotericsoftware.kryo.Kryo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.junit.Test;

import java.io.IOException;
import java.util.Arrays;


public class SerializationUtils {
    
    @Test
    public void jDKSerializationTest() throws IOException, ClassNotFoundException {
        System.out.println("JDK原生序列化Serializable");
        UserDTO userDTO = new UserDTO("jerry", "12", "123");
        byte[] bytes = JDKSerializationUtil.serialize(userDTO);
        System.out.println("【JDK原生序列化Serializable】序列化成功:" + Arrays.toString(bytes));
        System.out.println("【JDK原生序列化Serializable】byte size=" + bytes.length);

        UserDTO userDTO1 = JDKSerializationUtil.deSerialize(bytes);
        System.out.println("【JDK原生序列化Serializable】反序列化成功:" + userDTO1);
    }

    
    @Test
    public void fastJsonSerializationTest() {
        System.out.println("fastJson序列化");
        UserDTO userDTO = new UserDTO("jerry", "12", "123");
        //将一个对象序列化为 json 字符串:
        String userJsonString = JSON.toJSONString(userDTO);
        System.out.println("【fastJson】序列化成功,userJsonString:" + userJsonString);

        UserDTO userDTO2 = JSON.parseObject(userJsonString, UserDTO.class);
        System.out.println("【fastJson】反序列化成功,userDTO2:" + userDTO2);
    }

    
    @Test
    public void kryoSerializationTest() {
        System.out.println("Kryo序列化");
        UserDTO userDTO = new UserDTO("jerry", "12", "123");

        Kryo kryo = new Kryo();
        kryo.setRegistrationRequired(false);
        // kryo.register(UserDTO.class);
        byte[] kryoBytes = KryoSerializationUtil.serialize(userDTO, kryo);
        System.out.println("【Kryo】序列化成功:" + Arrays.toString(kryoBytes));
        System.out.println("【Kryo】byte size=" + kryoBytes.length);

        UserDTO userDTO3 = KryoSerializationUtil.deSerialize(kryoBytes, UserDTO.class, kryo);
        System.out.println("【Kryo】反序列化成功:" + userDTO3);
    }

    
    @Test
    public void jacksonSerializationTest() throws JsonProcessingException {
        System.out.println("Jackson序列化");
        UserDTO userDTO = new UserDTO("jerry", "12", "123");
        
        ObjectMapper mapper = new ObjectMapper();
        // User类转JSON
        String json = mapper.writevalueAsString(userDTO);
        System.out.println("【Jackson序列化】序列化成功:" + json);

        // JSON解析
        UserDTO userDTO2 = mapper.readValue(json, UserDTO.class);
        System.out.println("【Jackson序列化】反序列化成功:" + userDTO2);
    }

    
    @Test
    public void gsonSerializationTest() throws JsonProcessingException {
        System.out.println("gson序列化");
        UserDTO userDTO = new UserDTO("jerry", "12", "123");

        // User类转JSON
        Gson gson = new Gson();
        String json = gson.toJson(userDTO);
        System.out.println("【gson序列化】序列化成功:" + json);

        // JSON解析
        UserDTO userDTO2 = gson.fromJson(json, UserDTO.class);
        System.out.println("【Jackson序列化】反序列化成功:" + userDTO2);
    }

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777856.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号