看我在Map<String, String>集合中,存入Integer类型数据
Posted 默辨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了看我在Map<String, String>集合中,存入Integer类型数据相关的知识,希望对你有一定的参考价值。
文章目录
一、前情提要
前几天测试给我提了一个缺陷,提示类型转化报错,可是我怎么看对应的代码都想不明白问题在哪里
1、缺陷背景
将模型大致抽象一下,就是其他同事将前台的数据放入到一个map中,然后再把这个map转为json字符串传给后台,紧接着再把这个json字符串反序列化为一个map对象,最后把这个map对象传递给我。
2、报错提示如下:
光看报错提示,其实还是很开心的,这明显是一个类型转化异常,那必然是我将一个Integer类型的数字转化为一个String类型的字符串导致的,继续往下看
3、代码报错的位置
定位到报错的位置是下面的方法,然后我陷入了沉思,String转Integer?你这是哪门子的类型转化异常?我这不是两个String?
4、该方法只是一个简单的判空方法
二、寻找问题
1、捞日志看接收参数
心里窃喜,还好我把接收的参数打印在了日志里面。结果发现我在打日志的时候是直接传的map,并没有对其进行自定义的序列化,以至于我无法看到数据对应的类型(后文会说明,这个数据类型很重要),下次自己得记住要序列化
2、观察前台传给后台的参数
无奈,我只能前台看对应的参数情况,最终在前台的参数里面找到了它。发现一个参数不像是字符串
3、再次执行判断方法
然后我用数字类型的参数去执行StringUtils.isNotBlank()方法,只能说这个错误对味了。
但是新问题来了:
- 如果直接是数字编译通不过呀!
- 就算是Object类型的参数,我这里还需要强转,可是我的代码没有强转呀!
- 还有就是我报错的方法的参数泛型为Map<String,String>,泛型限定为String类后都不能接收Integer类型的参数呀!真的吗?
4、于是在阅读了同事的代码之后,再次定位问题
同事的工作其实就是把前台给的json字符串,反序列化为一个Map<String,String>的集合中。那么问题只能是在这个反序列化了,明明传进去的时候都还有数字,怎么出来就没有数字了?
三、验证问题
1、自己反序列化测试
模拟全过程代码
public class Map泛型兼容
public static void main(String[] args)
// 模拟前台的传给后台的数据
Map<String, Object> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", "a");
String jsonStr = "";
jsonStr = JSON.toJSONString(map);
// 传给后台的json字符串
System.out.println(jsonStr);
// 对字符串进行反序列化
Map<String, String> params = JSON.parseObject(jsonStr, HashMap.class);
for (Map.Entry<String, String> entry : params.entrySet())
if (entry.getValue() instanceof String)
else
System.out.println("不是字符串类型");
System.out.println(entry.getValue());
我们惊奇的发现,居然不报错,他居然不报错,他居然不报错,Integer的转化为String居然没问题,并且最终拿到数据的时候也还是Integer类型,我直接好家伙。
然后我就联想了一下json反序列化是通过反射完成的。
2、反射再验证
它居然还真可以,我使用反射向Map<String,String>的对象中添加数据,然后遍历该map对象,但是却发现其value是一个Integer类型。
那么一切就说的通了
验证代码:
public class TestReflect
public static void main(String[] args) throws Exception
Map<String, String> map = new HashMap<>();
Method put = map.getClass().getMethod("put", Object.class, Object.class);
put.invoke(map, "key1", 1);
put.invoke(map, "key2", "value2");
System.out.println(JSON.toJSON(map));
for (Map.Entry<String, String> entry : map.entrySet())
if (entry.getValue() instanceof String)
else
System.out.println("该key是其他类型:" + entry.getValue().getClass());
3、结论
最终的结论就是,同事在把前台的所有参数传到后台的时候,里面包含了一个value为Integer类型的数据,那类比就是放到了一个Map<String,Object>的map集合中,在对该map进行序列化后,就变成了一个普通的json字符串。
问题的关键就在于反序列这个位置,在对该json字符串反序列化的时候,就出现了问题。但是这个属于运行时异常了。因为我们的json字符串里面含有Integer类型的参数,但是反序列化的对象却是一个String类型,根据前文的演示,在利用反射进行赋值的时候,并不会报错,以至于一切风平浪静。
但当在我们在使用对应参数的时候,问题就来了,因为我们只认反序列化回的String类型的map,但是实际拿到的却是Integer,以至于引发了后续的错误。
那我们应该如何使用呢?
在我看来我们如果无法明确参数是否可能存在多种类型,可以使用Object类型的map接收反序列出来的集合数据,在获取对应参数的时候也不要使用强转的形式,而是使用更加友好的String.valueOf获取对应的内容(其底层就是调用包装类型的toString方法)
以上是关于看我在Map<String, String>集合中,存入Integer类型数据的主要内容,如果未能解决你的问题,请参考以下文章