同事用双括号来构建Map,害我一下午来解决bug

1. 项目场景:

我在将一个对象序列化存到redis队列中,发现总是报序列化异常的错误

2022-07-05 21:20:45.522 ERROR 3177 --- [nio-8095-exec-2] SerializeUtil工具类                         : serialize处发生一个异常,参数value:SendMsgReq(token=c7cc8f376ffd482ba9b1fc934e28f6d5, requestId=388a5924D0R85Lsx29Ev7ru63DOXoQ86, eventCode=registerAccountMs, params={telephone=17806169286, telphoneEnd=9286, smsCode=527535}, eventVarPackage=[ActDriveReq(actCode=act_t2ehn28, actName=null, actVariable={smsCode=527535, telephone=17806169286}, sendTarget=null, sendContent=null)])

java.io.NotSerializableException: com.mintrust.ms.service.impl.SmsSendTranService
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at com.mintrust.commonutil.utils.SerializeUtil.serialize(SerializeUtil.java:26)
	at com.mintrust.ms.service.impl.MsServiceImpl.unifyMsgSend(MsServiceImpl.java:174)

而我在序列化对象的时候明明是将对象实现了Serializable序列化接口的,也添加了序列化ID,为啥报没有序列化Service服务类的异常呢? 我真的是百思不得其解,我只是序列化了一个对象而已,难不成我将Service类进行序列化?
在序列化Service类之后出现了新的问题:
在这里插入图片描述
jar包里的类真的没有办法继续序列化了…

2. 问题发现

后来经过排查代码发现原来是同事用了双括号来构建了Map,通过断点可以看到:
在这里插入图片描述
咦,我这里明明定义的是一个Map,可是这里的SmsSendTranService代表了个啥?

在这里插入图片描述
正常来说这里应该是这样:
在这里插入图片描述
这才是我们想要的Map啊,为啥给我整一个SmsSendTranService$1 ?
后来通过查看同事的代码,发现了这样的写法:
在这里插入图片描述
通过查阅资料得出:
这里利用了内部类语法,这种方式比先new出对象然后再进行依次add要方便、简洁许多。该方法称之为“双括号初始化”(double brace initialization)。
在这里插入图片描述
显然这是在HashMap的构造器中写了一个匿名内部类,这个匿名内部类含有一个实例初始化块,初始化块的内容是三个add()函数,向被初始化的this指向的HashMap中添加了三个元素。

3.效率问题

利用双大括号初始化集合从效率上来说可能不如标准的集合初始化步骤。原因在于使用双大括号初始化会导致内部类文件的产生,而这个过程就会影响代码的执行效率。

假设有一个Test1类,里面有1000个list,都是使用双括号初始化,编译后如下:

Test1$1.class
Test1$2.class
...
Test1$1000.class

这也就是为啥第一次传参的时候出现了SmsSendTranService$1的问题,我要的是一个实现了序列化接口的Map,他直接给我传了一个内部类过来,在序列化内部类的时候,肯定会也序列化他的外部类,所以这就是为啥我报的那第一个错,没有序列化Service的原因。
我真的给我整无语了…

4.解决方法

后来我是通过将这个对象转化为String类型的JSON串,然后又转成了对象,绕了一圈,来躲掉这个中招的引用,
在这里插入图片描述

5.总结建议

虽然双括号语法看起来,更简洁,但是一定要慎用!!!尤其是在调别人接口的时候…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值