`
longdick
  • 浏览: 584942 次
  • 性别: 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
分享到:
评论

相关推荐

    Gson解析之自定义序列化和反序列化

    自定义序列化主要是为了在转换Java对象为JSON时,根据特定需求控制JSON输出的格式。这可以通过实现`com.google.gson.JsonSerializer<T>`接口来完成。假设我们有一个`User`类,其中包含一个日期类型的`birthday`字段...

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

    通过自定义反序列化方法,我们可以灵活地处理各种复杂的数据映射需求,将JSON数据准确无误地转换成Java对象,以供后端业务逻辑处理。这一过程不仅涉及到Java反射机制的运用,同时也需要对JSON格式有深入的理解。对于...

    java对象序列化和反序列化

    **三、自定义序列化与反序列化** 1. **序列化回调**:可以重写`writeObject()`和`readObject()`方法来自定义序列化和反序列化的行为,例如处理静态字段、处理特定逻辑等。 2. ** serialVersionUID**:为了保证序列...

    Java对象序列化标准最新版

    ### Java对象序列化标准知识点详解 #### 一、系统架构概览 **1.1 概览** Java 对象序列化是一种将Java对象的状态转换成字节流的过程,以便于在网络上传输或存储到磁盘上。Java序列化标准定义了一套规则来描述如何...

    Protocol Buffer序列化对比Java序列化.

    - Protocol Buffer:PB在序列化和反序列化时通常比Java序列化更快,因为它的数据格式更加紧凑,且解析算法优化。 - Java序列化:Java序列化虽然方便,但生成的数据量较大,且序列化和反序列化速度相对较慢。 2. ...

    Java Json序列化与反序列化

    三、自定义序列化与反序列化 在某些情况下,我们可能需要对特定的字段或对象进行自定义处理。Jackson和Gson都提供了这样的功能: - Jackson中的`@JsonSerialize`和`@JsonDeserialize`注解可以指定自定义的序列化器...

    Java安全漫谈 - 07.反序列化篇(1)1

    2. **脆弱的自定义序列化**:在`readObject`方法中直接执行未经验证的用户输入,可能导致代码执行。 3. **反射滥用**:攻击者可以通过序列化数据控制反射调用,执行敏感方法或构造对象。 4. **第三方库的不安全实现*...

    jackson库实现定制化的java序列化反序列化操作

    标题中的“jackson库实现定制化的java序列化反序列化操作”指的是利用Jackson库的能力,通过自定义规则来控制对象的序列化和反序列化过程。这通常涉及到创建自定义的`JsonSerializer`和`JsonDeserializer`,或者使用...

    JAVA对象序列化保存为XML文件的工具类

    【JAVA对象序列化保存为XML文件的工具类】 在Java编程中,对象序列化是一种将对象的状态转换为字节流的过程,以便可以存储或在网络上传输。而在反序列化时,这个字节流又可以恢复为原来的对象。Java提供了一个方便...

    java基础 对象序列化

    `Serializable`是一个标记接口,而`Externalizable`则提供了更精细的控制,允许开发者自定义序列化和反序列化的过程。 #### 实现对象序列化 实现序列化的基本步骤包括: 1. **实现接口**:使类实现`Serializable`...

    JAVA基于SnakeYAML实现解析与序列化YAML

    JAVA基于SnakeYAML实现解析与序列化YAML JAVA基于SnakeYAML实现解析与序列化YAML是JAVA开发中的一种常见需求,本文主要介绍了如何使用SnakeYAML库将YAML文档转换为Java对象,以及Java对象如何序列化为YAML文档。...

    Netty服务端与客户端依靠Java序列化传输数据

    4. **自定义序列化解码器**: 虽然Java序列化是内建的,但在实际应用中,可能需要自定义编码和解码器以满足特定需求。例如,可以创建一个`JavaSerializationDecoder`和`JavaSerializationEncoder`,分别负责在接收...

    深入剖析Java序列化:挑战复杂的面试题与详细解析

    - 显示指定`serialVersionUID`,或使用自定义序列化策略。 14. **Java序列化与JSON序列化比较**: - Java序列化:针对Java对象,字节流形式。 - JSON序列化:文本形式,跨语言跨平台。 15. **禁止类序列化**: ...

    探索Java序列化与反序列化的奥秘:数据持久化的桥梁

    2. **实现Externalizable接口**:如果需要更多控制权,可以选择实现`Externalizable`接口,该接口要求实现`writeExternal()`和`readExternal()`方法,从而可以自定义序列化和反序列化的逻辑。 #### 示例代码:序列...

    hessian学习基础篇——序列化和反序列化

    这对于优化自定义序列化逻辑或者解决Hessian使用中遇到的问题非常有帮助。 总结起来,Hessian是一种高效、轻量级的二进制序列化协议,特别适合于跨语言的网络通信。理解并掌握Hessian的基本概念和使用方法,能够...

    java高效对象序列化反序列化工具kryo-2.21

    3. **可配置性**:Kryo允许用户自定义序列化策略,例如选择特定的序列化器,或者为特定字段排除序列化。 4. **串行化深度控制**:可以限制序列化深度,防止无限递归和内存消耗。 5. **兼容性**:Kryo提供了版本控制...

    几种序列化的实现方法 java自带, Writable, Avro

    Avro的序列化数据紧凑且高效,同时支持动态类型,使得数据结构的变化不会导致旧数据无法解析。Avro的主要特点包括: - 数据模式驱动:通过Schema定义数据结构,易于理解且跨语言兼容。 - 动态Typing:即使Schema...

    jackson json序列化,反序列化所需jar包

    在实际开发中,你可能还需要配置`ObjectMapper`以满足特定需求,比如日期格式化、忽略未知属性、自定义序列化策略等。这可以通过设置`ObjectMapper`的配置属性或者使用注解来实现。 为了在项目中使用这些jar包,你...

    springboot-fastjson-auto-transform-enum.zip

    Fastjson提供了一些内置的策略,但可能无法满足所有需求,此时就需要自定义序列化和反序列化规则。 4. **自定义序列化器(Serializer)** 创建一个实现了`com.alibaba.fastjson.serializer.SerializerFeature`接口...

    Gson 枚举类型的统一序列化/反序列化处理

    本篇文章将详细探讨如何通过自定义Gson适配器实现枚举类型的统一序列化和反序列化处理,无需预先定义枚举,也无需修改Gson源码。 首先,Gson是Google提供的一个开源库,用于在Java对象和JSON数据之间进行映射。默认...

Global site tag (gtag.js) - Google Analytics