看我在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()方法,只能说这个错误对味了。

但是新问题来了:

  1. 如果直接是数字编译通不过呀!
  2. 就算是Object类型的参数,我这里还需要强转,可是我的代码没有强转呀!
  3. 还有就是我报错的方法的参数泛型为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类型数据的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中map中存储list集合问题。

获取map集合中的键和值

遍历Map集合

如何创建Map集合?

mybatis里怎么获取传进去的map集合中的key

集合框架 ----------Map集合遍历的方法