`
longdick
  • 浏览: 579953 次
  • 性别: Icon_minigender_1
  • 来自: 0
社区版块
存档分类
最新评论

Java自定义序列化行为解析

阅读更多

正常情况下,一个类实现java序列化很简单,只需要implements Serializable接口即可,之后该类在跨jvm的传输过程中会遵照默认java序列化规则序列化和反序列化;不同jvm版本之间序列化方式稍有不同,但基本上都是兼容的。

在某些特殊情况下,可能需要自定义序列化和反序列化的行为,看下面例子:

 

class AbstractSerializeDemo {
    private int x, y;

    public void init(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void printXY() {
        System.out.println("x:" + x + ";y:" + y);
    }
}

public class SerializeDemo extends AbstractSerializeDemo implements Serializable {
    private int z;

    public SerializeDemo() {
        super.init(10, 50);
        z = 100;
    }

    public void printZ() {
        super.printXY();
        System.out.println("z:" + z);
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        SerializeDemo sd = new SerializeDemo();
        sd.printZ();
        out.writeObject(sd);
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        SerializeDemo sd2 = (SerializeDemo) in.readObject();
        sd2.printZ();
    }
}
 

 

 

这段程序表示了一个可序列化的类继承自一个非序列化的有状态超类,期望的结果是,子类序列化以后传输并反序列化回来,原先的值域包括超类的值域都保持不变。

但是输出是:

x:10;y:50
z:100
x:0;y:0
z:100
 

 

 

结果和期望不符,子类的值域保留下来了,但是超类的值域丢失了,这对jvm来说是正常的,因为超类不可序列化;

为了解决这个问题,只能自定义序列化行为,具体做法是在SerializeDemo里加入以下代码:

 

 

  private void writeObject(ObjectOutputStream os) throws IOException {
        os.defaultWriteObject();//java对象序列化默认操作
        os.writeInt(getX());
        os.writeInt(getY());
    }

    private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
        is.defaultReadObject();//java对象反序列化默认操作
        int x=is.readInt();
        int y=is.readInt();
        super.init(x,y);
    }
 

 

 

writeObject和readObject方法为JVM会在序列化和反序列化java对象时会分别调用的两个方法,修饰符都是private,没错。

我们在序列化的默认动作之后将超类里的两个值域x和y也写入object流;与之对应在反序列化的默认操作之后读入x和y两个值,然后调用超类的初始化方法。

再次执行程序之后的输出为:

 

x:10;y:50
z:100
x:10;y:50
z:100


 

另外还有两个自定义序列化方法writeReplace和readResolve,分别用来在序列化之前替换序列化对象 和 在反序列化之后的对返回对象的处理。一般可以用来避免singleTon对象跨jvm序列化和反序列化时产生多个对象实例,事实上singleTon的对象一旦可序列化,它就不能保证singleTon了。JVM的Enum实现里就是重写了readResolve方法,由JVM保证Enum的值都是singleTon的,所以建议多使用Enum代替使用writeReplace和readResolve方法。

 

 

private Object readResolve()
    {
        return INSTANCE;
    }
   
    private Object writeReplace(){
        return INSTANCE;
    }


 

注:writeReplace调用在writeObject前;readResolve调用在readObject之后。

 

1
3
分享到:
评论

相关推荐

    实例解析Json反序列化之ObjectMapper(自定义实现反序列化方法)

    主要介绍了实例解析Json反序列化之ObjectMapper,json自定义序列化的方法,需要的朋友可以了解下。

    java常用类解析及示例及一些工具类源代码

    主要讲解了System类、Object类、Arrays类、Cloneable接口、IO系统输入输出类及装饰类、IO系统文本读写工具类、IO系统二进制读写工具类、对象序列化工具类、File类及文件搜索工具类、java异常机制及自定义异常类、...

    springboot整合Jackson实例项目-附工具类

    与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。 额外了解: Jackson 的 1.x ...

    gson-2.8.6.jar下载

    3. 支持用户自定义序列化和反序列化的规则。可以直接将gson和bean-validation框架结合,校验Java对象的字段。 4. 支持基本数据类型及其封装类型,Collection类型,Date类型及自定义类型。 5. 支持将JSON数组转换为Java...

    java常用映射器(b站黑马程序员瑞吉外卖代码资源)

    java常用映射器(b站黑马程序员瑞吉外卖代码资源) * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象 ...可以添加自定义序列化器和反序列化器。可以将long类型映射位sting类型。

    fluentxml4j:Java中用于XML解析,序列化,XPath查询和转换的fluent API

    XML解析,序列化XPath查询和转换,无需样板代码 产品特点 简单,流畅的API,但完全灵活 从java.io输入解析到org.w3c.dom.Document 将org.w3c.dom.Document序列化为任何java.io输出 通过XSLT和自定义过滤器支持将...

    jsonbeans, Java对象图,自动和从 JSON.zip

    jsonbeans, Java对象图,自动和从 JSON JsonBeans请使用 JsonBeans...概述编写对象图读取对象图自定义序列化插件基于事件的解析概述JsonBeans是一个轻量级库,可以轻松地将Java对象图序列化和反序列化到 JSON 。 jar

    java源码包---java 源码 大量 实例

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    JAVA上百实例源码以及开源项目源代码

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    JAVA上百实例源码以及开源项目

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    Java开发技术大全(500个源代码).

    Student.java 定义一个用来序列化的类 ThreadIn.java 接收数据用的线程类 ThreadOut.java 发送数据用的线程类 TypeFile.java 显示文件内容的类 useScanner.java 用Scanner接收用户的输入 第8章 示例描述:本章...

    java jdk实列宝典 光盘源代码

    序列化和反序列化对象(将不长用的对象暂时持久化到文件中为对象的序列化,反之用时再把对象恢复到内存为反序列化); 控制对象的序列化和反序列化; 读jar包的资源文件;用zip格式压缩 和解压文件;操作Excel文件;...

    java源码包4

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    java源码包3

     Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    java开源包4

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包101

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包11

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包6

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包9

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

Global site tag (gtag.js) - Google Analytics