java Serializable 一些细节

本文详细介绍了网络传输对象的序列化原则,包括实现Serializable接口、无参构造器、枚举类型避免、序列化ID设定等关键点,旨在帮助开发者有效解决网络通信中的序列化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1)通过网络传输的对象,必须实现Serializable接口,或者父类已经实现序列化接口。

(2)网络传输对象封装太多层次的父类不太好,或者说在interface上用父类定义,然后将子类实例传递给网络另一端的应用可能没这个 jar包/class,反序列化不了的。另一可能情况,动态代理接口InvocationHandler invoke(Object proxy, Method method, Object[] args),传进时,method的参数定义匹配interface上的method参数定义,比如是父类,从args获取的class是子类,如果某种 rpc技术处理不当,或无从识别,困扰的是使用者。

(3)网络接口上的参数、返回值类型、会抛出的异常类,都要实现序列化接口。包括层层里面装着的内容,父类(比较少人对这field推敲private/protected,父类可能有直接被使用的时候)。

(4)ArrayList.subList()返回的List实现类是内部类型,不能序列化的,通过网络传输会出错。

(5)网络对象第一次上线使用时,就要设定serialVersionUID,不要不顾编译警告

网络对象的匹配,除了靠类名,还靠serialVersionUID,serialVersionUID在《Java语言规范》有固定算法,跟各field的定义相关,如果没有显式赋值,虽然看不见,但会底下会默认算出一个进行网络传输。

如果没有显式赋值,也在你看不见觉察不到的情况下,在你增减了field/修改了定义的情况下,serialVersionUID已被改 变,这时网络两端就对接不上而悲剧了。没定义serialVersionUID,而又发生了serialVersionUID变化,网络两端只有所有机器 都停掉,并且先后起有顺序时,才能不出丝毫差错。

(6)网络传输对象要有无参构造器,因为机器系统是不知道传什么内容给有参构造器进行实例化,无参构造器不是public都没关系。没定义无参构造器,有些序列化方式会在底下生成无参构造器的方式才能解决问题。

(7)网络传输最好不要用enum类型,太强耦合,从网络一端传到另一端,对方可能还是旧版本而识别不了。别人文章里有enum的序列化说明

(8)有的人喜欢用1L作为serialVersionUID,但不知道是否是通配值,一开始就有赋值肯定没错,0L对于java enum的序列化有特殊意义。

(9)看看HashMap、Date的源代码,不需通过网络传输的field用transient定义,然后实现writeObject等方法。不是所有场合都识别Externalizable,或许都要此场合特别支持Externalizable才行。

(10)有些系列化格式,遇到反序列化不了的类,会反序列化成Map,但会在使用时遇到class cast异常。

(11)不用抛客户端没有jar的异常类到客户端

(12)同一应用不要有同package同名类,即使隐藏在同名/不同名/不同版本的jar中。

(13)远程调用、分布式调用,分布式缓存等,或许都需要经过序列化,虽然让你透明地使用网络/感觉不到。

(14)不要序列化大数据对象/十分复杂对象,一般long/int/String/Map/List/Array等常见类组成的对象就已能解决问题,最好不要在本应用的业务接口传递/返回另一人主导业务/结构的对象。 不是建议不要用ArrayList,只是要注意ArrayList经过网络后可能顺序不一样。两需一一对应的List,经过网络后不一定一一对应。List中有零星的null,可能会给别人造成麻烦。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值