java自定义序列化的具体使用

目录
  • 1.问题引出
  • 2.解决办法
  • 3.另外一种自定义序列化机制(介绍Externalizable)

1.问题引出

在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Serializable接口。

java中的序列化是递归序列化,也就是你的field的引用类型中也有field可以被序列化,那么就会在序列化当前对象的时候,一同序列化

2.解决办法

使用transient(瞬变现象;过往旅客;候鸟)关键字来修饰,该关键字只能修饰属性,这样在序列化的时候,这个属性就会用默认值,例如int类型用0,引用对象用null;

但是使用transient关键字修饰的field虽然简单方便,但是会被完全隔离在序列化机制之外,这样导致在反序列化回复java对象的时候,无法取得该field的值。

因此我们可以使用自定义序列化机制,可以让程序控制如何序列化各field,甚至完全不序列化某些field(这样就与transient相同),在序列化和反序列化过程中需要特殊处理的类应该提供如下特殊签名的方法,这些特殊的方法用以实现自定义的序列化

private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in)throws IOException,ClassNotFoundException;
private void readObejctNoData()throws ObejctStreamException;

热爱你所写的每一行的代码

writeObject()方法负责写入特定类的实例状态,通过重写这个方法,程序员可以完全获得对序列化机制的控制,可以自主决定那些field需要序列化,需要怎么序列化,默认情况(函数体为空)该方法会调用out.defaultWriteObject来保存java对象的各field,从而达到实现序列化java对象状态的目的

readObject负责从流中读取并且回复对象的field,通过重写该方法,程序员,可以获得对反序列化机制的控制,对于反序列化各个field的顺序应该和序列化各个field的顺序相同。

至于当序列化流不完整时,readObjectNoData可以正确的初始化反序列化的对象,例如接收方接收到的序列化流残缺,或者序列化版本不同,则使用readObjectNoData来默认的初始化。

例子(对于person的改写):

class Person implements Serializable
{
 private String name;
 private int age;
 public Person(String name,int age)
 {
  this.name=name;
  this.age=age;
 }
 //自动生成的Get和Set方法
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 private void writeObject(ObjectOutputStream out) throws IOException
 {
  //将名字翻转之后写入二进制流
  out.writeObject(new StringBuffer(this.name).reverse());
  out.writeInt(this.age);
 }
 private void readObject(ObjectInputStream in)throws IOException,ClassNotFoundException
 {
  this.name=((StringBuffer)in.readObject()).reverse().toString();
  //会抛出异常,因为这里的这样写法导致同
  this.age=in.readInt();
 }
}

应该提醒的是,这个自定义的功能十分强大

另外一种替换性的改写:

//注意:这个方法由序列化机制调用,只要该方法存在就,它的访问控制符就可以为private protected package-private中的任意一种
 private Object writeReplace() throws ObjectStreamException
 {
  ArrayList<Object> list=new ArrayList<>();
  list.add(name);
  list.add(age);
  //我们这里返回ArrayList
  return list;
 }

序列化机制保证在序列化某个对象之前,先调用该对象的writeReplace方法,如果该方法返回另外一个java对象,系统就转换为序列化writeReplace的返回结果。(ps:如果这个返回结果也有writeReplace方法的话,就继续递归替代,直到没有替换)

相应与writeReplace相对的有一个readResolve方法,这个方法保护性的赋值整个对象,这里就不展开讨论了。

3.另外一种自定义序列化机制(介绍Externalizable)

Java还提供了另一种序列化机制,这种序列化方式完全由程序员决定存储和恢复对象数据。要实现该目标,Java类必须实现Externalizable接口,该接口里定义了如下两个方法。

  • void readExternal(ObjectInput in):需要序列化的类实现readExternal()方法来实现反序列化。该方法调用DataInput(它是ObjectInput的父接口)的方法来恢复基本类型的Field值,调用ObjectInput的readObject()方法来恢复引用类型的Field值。
  • void writeExternal(ObjectOutput out):需要序列化的类实现writeExternal()方法来保存对象的状态。该方法调用DataOutput(它是ObjectOutput的父接口)的方法来保存基本类型的Field值,调用ObjectOutput的writeObject()方法来保存引用类型的Field值。

具体的实现方式与上面自定义Serializable接口的实现类的序列化是相同的操作,这里就不阐述了,下面图是二者的比较。

到此这篇关于java自定义序列化的具体使用的文章就介绍到这了,更多相关java自定义序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java 中序列化NotSerializableException问题解决办法

    java 中序列化NotSerializableException问题解决办法 前言: 某项目中,要将某个自定义类MMessage对象,通过ObjectOutputStream和ObjectInputStream传递,该MMessage的特征描述: 1 该类未继承Serializable接口: 2 其父类Message的父类继承了Serializable接口: 3 其父类中有一个字段类型为Java.io.ByteArrayOutputStream类型: 经测试发现,MMessage类序列化过程中

  • java 序列化对象 serializable 读写数据的实例

    序列化对象: 复制代码 代码如下: package com.chen.seriaizable; import java.io.Serializable;import java.util.List; @SuppressWarnings("serial")public class Student implements Serializable{ private String name; private String id; private int age; private List<

  • Java中对象序列化与反序列化详解

    本文实例讲述了Java中对象序列化与反序列化.分享给大家供大家参考.具体如下: 一.简介 对象序列化(Serializable)是指将对象转换为字节序列的过程,而反序列化则是根据字节序列恢复对象的过程. 序列化一般用于以下场景: 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.通过序列化对象在网络中传递对象: 3.通过序列化在进程间传递对象. 对象所属的类必须实现Serializable或是Externalizable接口才能被序列化.对实现了Serializable接口的类,其序列化

  • Java实现序列化与反序列化的简单示例

    1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化与反序列化 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本.图片.音频.视频等, 而这些数据都会以二进制序列的形式在网络上传送.那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的.如何做到呢?这就需要Java序列化与反序列化了.换句话说,一方面,发送方需要把这个Java对象转换为字节序

  • 浅谈java中为什么实体类需要实现序列化

    当客户端访问某个能开启会话功能的资源,web服务器就会创建一个HTTPSession对象,每个HTTPSession对象都会占用一定的内存,如果在同一个时间段内访问的用户太多,就会消耗大量的服务器内存,为了解决这个问题我们使用一种技术:session的持久化. 什么是session的持久化? web服务器会把暂时不活动的并且没有失效的HTTPSession对象转移到文件系统或数据库中储存,服务器要用时在把他们转载到内存. 把Session对象转移到文件系统或数据库中储存就需要用到序列化: jav

  • java序列化和java反序列化示例

    序列化一般应用与以下场景之中:1.永久性保存对象,把对象通过序列化字节流保存到本地文件中:2.通过序列化在网络中传输对象3.通过序列化在进程间传递对象 复制代码 代码如下: import java.io.Serializable;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream; public class javaSerializable_fun { /**  

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

    这篇文章主要介绍了JAVA基于SnakeYAML实现解析与序列化YAML,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.概述 本文,我们将学习如何使用SnakeYAML库将 YAML文档转换为Java对象,以及JAVA对象如何序列化为YAML文档. 2.项目设置 要在项目中使用SnakeYAML,需要添加Maven依赖项(可在此处找到最新版本): <dependency> <groupId>org.yaml</group

  • Java实现几种序列化方式总结

    0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生序列化方法即通过Java原生流(InputStream和OutputStream之间的转化)的方式进行转化.需要注意的是JavaBean实体类必须实现Serializable接口,否则无法序列化.Java原生序列化代码示例如下所示: package serialize; import java.io

  • java自定义序列化的具体使用

    目录 1.问题引出 2.解决办法 3.另外一种自定义序列化机制(介绍Externalizable) 1.问题引出 在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Serializable接口. java中的序列化是递归序列化,也就是你的field的引用类型中也有field可以被序列化,那么就会在序列化当前对象的时候,一同序列化 2.解决办法 使用transient(瞬变现象:过往

  • java原生序列化和Kryo序列化性能实例对比分析

    简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等 这些序列化方式的性能多数都显著优于hessian2(甚至包括尚未成熟的dubbo序列化).有鉴于此,我们为dubbo引入Kryo和FST这 两种高效Java序列化实现,来逐步取代hessian2.其中,Kryo是一种非常成熟的序列化实现,已经在Twitter.Group

  • 浅谈Java自定义注解和运行时靠反射获取注解

    java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能. 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annotation 包中. 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1.1.@Retention: 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅

  • 理解Java的序列化与反序列化

    文章主要涉及到以下几个问题: 怎么实现Java的序列化 为什么实现了java.io.Serializable接口才能被序列化 transient的作用是什么 怎么自定义序列化策略 自定义的序列化策略是如何被调用的 ArrayList对序列化的实现有什么好处 一.Java对象的序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但在现实应用中,就可能要求在JVM停止运行之后能够保存

  • 详解Java 对象序列化和反序列化

    之前的文章中我们介绍过有关字节流字符流的使用,当时我们对于将一个对象输出到流中的操作,使用DataOutputStream流将该对象中的每个属性值逐个输出到流中,读出时相反.在我们看来这种行为实在是繁琐,尤其是在这个对象中属性值很多的时候.基于此,Java中对象的序列化机制就可以很好的解决这种操作.本篇就简单的介绍Java对象序列化,主要内容如下: 简洁的代码实现 序列化实现的基本算法 两种特殊的情况 自定义序列化机制 序列化的版本控制 一.简洁的代码实现 在介绍对象序列化的使用方法之前,先看看

  • 详解Java对象序列化为什么要使用SerialversionUID

    1.首先谈谈为什么要序列化对象 - 把对象转换为字节序列的过程称为对象的序列化. - 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器

  • spring-session自定义序列化方式

    目录 spring-session自定义序列化 自定义序列方法使用jackson库 配置spring-session序列化 spring-session序列化问题排查 问题 解决方法 spring-session自定义序列化 spring-session默认采用jdk序列化方法,该方法效率低下.内存占用大,且需要额外修改代码.故需要自定义序列化方法 自定义序列方法使用jackson库 首先需要一个类作为序列化的工具,需要实现 RedisSerializer 该接口在反序列化时没有提供对应的cla

  • Java高性能序列化工具Kryo详情

    目录 概述 基础用法 Kryo 的序列化 Kryo 的注册 Kryo 的序列化器 对象引用 线程不安全 ThreadLocal + Kryo 解决线程不安全 对象池 + Kryo 解决线程不安全 小结 概述 Kryo 是一个快速序列化/反序列化工具,依赖于字节码生成机制(底层使用了 ASM 库),因此在序列化速度上有一定的优势,但正因如此,其使用也只能限制在基于 JVM 的语言上. 和 Hessian 类似,Kryo 序列化出的结果,是其自定义的.独有的一种格式.由于其序列化出的结果是二进制的,

  • java自定义枚举转换器示例

    java自定义枚举转换器 复制代码 代码如下: import org.apache.commons.beanutils.Converter; /** * 自定义枚举转换器 *  *  */public class MyEnumConverter implements Converter { @Override // 将value 转换为 c类型 --- 枚举通用转换器 public Object convert(Class c, Object value) {  String strVal =

随机推荐