Map<String,Object>接收参数,Long类型降级为Integer,报类型转换异常

前言

今天看群里小伙伴问了一个非常有意思的问题:

使用 Map<String,Object> 对象接收前端传递的参数,在后端取参时,因为接口文档中明确该字段类型为 Long ,所以对接收的参数进行了强转,即 (Long)参数 ,但是却发生了类型转换异常,报错信息如下:

class java.lang.Integer cannot be cast to class java.lang.Long 
(java.lang.Integer and java.lang.Long are in module java.base of loader 'bootstrap')

发现好几个小伙伴也有疑惑,干脆直接码一篇文章解答一下,希望对有此疑惑的小伙伴有所帮助。

Long 类型降级

我们先通过测试数据、测试方法来还原一下问题。

测试json数据如下:

{"user_name": "niceyoo","age": -24,"money": 2147483646
}

测试test方法如下:

@PostMapping("/test")
@ResponseBody
public void test(@RequestBody Map<String,Object> params) {String userName = (String) params.get("user_name");Integer age = (Integer) params.get("age");Long money = (Long) params.get("money");System.out.println(String.format("user_name=%s,age=%s,money=%s",userName,age,money));
}

如上传递了三个参数,即用户名、年龄、金额这三个字段,如下是调用情况:

通过截图下方断点参数可以看到接收的 age 、money 都是 Interger 类型,而代码中 money 使用 Long 强转的话会报 java.lang.Long cannot be cast to java.lang.Integer 异常,至此问题就还原出来了。

不懂就问:为什么接收的 money 是 Integer 类型,强转后会报错?

首先我们先来看为什么接收的 money 是 Integer 类型。

使用 Map<String,Object> 接收的 Long 数值如果处于 「 Integer.MIN_VALUE ~ Integer.MAX_VALUE 」 是会自动转换成 Integer 的。

不光是接收,同样直接使用 Map<String,Object> 存入数据符合这个范围,仍然也会被认为存入的是 Integer 类型,我们可以把它看做一种潜在的优化,毕竟 Long 类型使用的字节数要大于 Integer 。

  • Integer.MAX_VALUE,Integer 类型的最大值,

  • Integer.MIN_VALUE,Integer 类型的最小值,

这两个值可以直接通过 sout 打印查看:

  • System.out.println(Integer.MAX_VALUE): 2147483647
  • System.out.println(Integer.MIN_VALUE): -2147483648

我们来验证一下,将 money 的值改成大于 Integer.MAX_VALUE:

同样的,如果传递的值小于 -2147483648,那么同样接收的类型为 Long,大家可以验证一下。

为什么强转后会报错?

强转的一些条件:

  • 低阶转高阶可以直接转;
  • 高阶转低阶需要强制转换,否则报错;
  • 强转 null 值报错;
  • 包装类型数据不支持直接跨类型强转;

其实报错的原因就是这最后一条,包装类型是不支持直接跨类型强转的,比如,你可以使用 Integer 跟 int 的直接转换,但是你不能将 Integer 直接强转成 Long 类型,或者 Long 类型强转 Integer ,这样都是报错的。

如果不能确定接收的对象是 Long 还是 Integer 怎么办?

既然知道不能强转了,但是如果不知道接收的对象是什么类型怎么办?

因为这种情况下,你不知道接收的对象到底是超过 Integer 这个范围还是没有超过。

第一种解决方法就是对接收的对象进行类型判断。

主要就是使用关键字 — instanceof

如图所示,我们可以先用 Object 接收一下对象,然后对其通过 instanceof 关键字进行类型判断,如果是 Integer 类型,则先 .toString(),然后再使用 Long.parseLong() 进行转换,如果本身就是 Long,则直接进行强转,同理,接收 Integer 类型也一样,无非就是换用 Integer.parseInteger().

第二种就是直接使用实体接收,使用实体接收就不会存在此问题了。

博客园持续更新,欢迎关注,希望这篇文章对你有所帮助。

博客园:https://www.cnblogs.com/niceyoo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/413879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

adb无法连接安卓手机

确保已安装好手机驱动&#xff08;在设备管理器中能找到安卓的设备&#xff09;查看设备的VID信息找到你的模拟器存放的目录&#xff0c;<例如&#xff1a;C:\Users\Administrator\.android 下找到或新建一个adb_usb.ini文件。文档内容写入VID即可 在cmd上输入adb kill-serv…

那些对你说学历不重要,技术重要的人,他们大部分都是有学历的。

随便唠叨几句 最近有挺多小伙伴在微信上私信我&#xff0c;咨询提升学历问题的&#xff0c;希望我能给点意见&#xff0c;当然&#xff0c;这里面大部分是涉及到专升本&#xff0c;因为自己是过来人&#xff0c;所以感触比较深&#xff0c;耐心的给予了回复&#xff0c;整理后…

前端学习(2856):简单秒杀系统学习之定时器循环显示

<html><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><title>javascrip</title></head><body ><script>function show() {console.log(每过1秒展示);}function show2(str) {…

SpringBoot中的Tomcat是如何启动的

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency>添加如上 Web 的依赖&#xff0c;Spring Boot 就帮我们内置了 Servlet 容器&#xff0c;默认使用的是 Tomcat&a…

json传输二进制的方案【转】

本文转自&#xff1a;http://wiyi.org/binary-to-string.html json 是一种很简洁的协议&#xff0c;但可惜的是&#xff0c;它只能传递基本的数型(int,long,string等)&#xff0c;但不能传递byte类型。如果想要传输图片等二进制文件的话&#xff0c;是没办法直接传输。 本文提供…

IDEA社区版(Community)和付费版(UItimate)的区别

比对类型Ultimate(终极版,付费)Community(社区版,免费)语言支持JavaJavaGroovyGroovyKotlinKotlinScala&#xff08;通过插件&#xff09;Scala&#xff08;通过插件&#xff09;Python 和 Jython&#xff08;通过插件&#xff09;Python 和 Jython&#xff08;通过插件&#x…

从使用传统Web框架到切换到Spring Boot后的总结

1、前言 其实我接触 Spring Boot 的时间并不长&#xff0c;所以还算一个初学者&#xff0c;这篇文章也算是我对 Spring Boot 学习以及使用过程中的复盘&#xff0c;如果文章出现描述错误或表达不清晰的地方&#xff0c;欢迎大家在评论区留言互动。 没想到 Spring Boot 这两年…

前端学习(2859):简单秒杀系统学习之前端界面布局

<html><head><meta charset"utf-8"><link rel"stylesheet" type"text/css" href"miao.min.css" charset"utf-8"><title>秒杀系统</title></head><body><div class"…

Spring Boot 项目瘦身指南,瘦到不可思议!129M->1.3M

之前在 从使用传统Web框架到切换到Spring Boot后的总结 中提到关于 Spring Boot 编译打包&#xff0c;Spring Boot 应用程序不用额外部署到外部容器中&#xff0c;可以直接通过 Maven 命令将项目编译成可执行的 jar 包&#xff0c;然后通过 java -jar 命令启动即可&#xff0c;…

基于Docker搭建RabbitMQ(多图)

1、一点废话&#xff08;可直接跳转至标题2&#xff09; 通常在拉取镜像之前&#xff0c;除了通过命令执行 docker search xxx 之外&#xff0c;我们还可以通过 Docker 镜像仓库查询指定的镜像。 如下是 rabbitmq 镜像的搜索结果&#xff1a; 一般拉取下载数 stars 数相对比…

基于Docker搭建Redis集群(主从集群)

最近陆陆续续有不少园友加我好友咨询 redis 集群搭建的问题&#xff0c;我觉得之前写的这篇 《基于Docker的Redis集群搭建》 文章一定是有问题了&#xff0c;所以我花了几分钟浏览之前的文章总结了下面几个问题&#xff1a; redis 数量太少&#xff0c;只创建了 3 个实例&…

洛达AirPods鉴别检测工具AB153x_UT,支持1562a 1562f

推荐阅读&#xff1a;AB1562_UT软件分辨真假洛达1562A&#xff0c;洛达1562a怎么鉴别&#xff1f; 洛达 1536u 1562a 1562f 1562m 检测工具&#xff0c; 可根据协议检测出实际使用芯片&#xff0c;免拆机检测华强北airpods使用芯片 一、使用方法 蓝牙连接安卓手机后&#x…

AB1562_UT软件分辨真假洛达1562A,洛达1562a怎么鉴别?

一、使用方法 1、下载并安装 AB1562_UT&#xff0c;下载链接 → https://t.1yb.co/kQIC 2、如上图所示&#xff0c;点击顶部的「选择设备」&#xff0c;弹出窗口中选择你的耳机。 3、点击「连接耳机」 4、显示耳机信息 更多测试方法请点击该链接&#xff1a;https://www.cnblo…

[js] callee和caller的区别和作用是什么?

[js] callee和caller的区别和作用是什么&#xff1f; arguments.callee 指的是当前函数 Function.caller 指的是调用当前函数的函数 举个例子&#xff1a;function a() {console.log(arguments.callee);console.log(a.caller); } function b() {a(); } b(); a();控制台输出&a…

niceyoo的2020年终总结-2021年Flag

碎碎念&#xff0c;向本命年说再见&#xff01; 又到了一年一度立 Flag 的时间了&#xff0c;怎么样&#xff0c;去年的 Flag 大家实现的怎么样&#xff1f;还有信心立下 2021 年的 Flag 吗~ 今年我算比较背的&#xff0c;年初的一次小意外&#xff0c;直接在床上躺了2月&…