专栏首页niceyooMap<String,Object>接收参数,Long类型降级为Integer,报类型转换异常
原创

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

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Netty入门篇-从双向通信开始

    Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、...

    niceyoo
  • 单招计算机类哪个专业好

    走单招,首先说明成绩是不理想的,我也是过来人,所以我不会劝你继续努努力,加加油,相信自己一定是考上诸如此类的话,我会就目前这个标题谈一谈我对单招计算机哪类专业好...

    niceyoo
  • @RequestParam,@RequestBody,@PathVariable注解还分不清吗?

    在使用 SpringMVC 开发时,经常遇到前端传递的各种参数,比如 form 表单,JSON 数据,String[] 数组,再或者是最常见的 String 字...

    niceyoo
  • 携程Apollo(阿波罗)配置中心在.NET Core项目快速集成

    张善友
  • 携程Apollo(阿波罗)配置中心在.NET Core项目快速集成

    .NET Core的支持文档大体上可以参考文档.Net客户端使用指南:https://github.com/ctripcorp/apollo/wiki/.Net...

    张善友
  • CentOS 8 安装 MariaDB的详细教程

    MariaDB 数据库管理系统是 MySQL 的一个分支,主要由开源社区在维护,采用 GPL 授权许可。开发这个分支的原因之一是:甲骨文公司收购了 MySQL ...

    砸漏
  • influxdb 简介与实现(一)

    InfluxDB是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及执行分析。

    Timu
  • python的strip()函数和rstrip()函数的用法总结

    声明:s为字符串,rm为要删除的字符序列. 只能删除开头或是结尾的字符或是字符串。不能删除中间的字符或是字符串。

    于小勇
  • 基于 Express 应用框架的技术方案选型浅谈

    现在的 Node 对于前端而言可以涵盖各个方面,包括命令行接口、插件、依赖库、脚手架以及 Web 服务等。本文是一篇对于 Node 使用的浅谈文章,会简单讲解一...

    前端迷
  • React 同构直出优化总结

    一提到 React,不得不提同构,同构基于服务端渲染,却不止是服务端渲染。本文结合手 Q 家校群上的具体实践,分享一些同构的 Tips 及优化成果。

    腾讯AlloyTeam

扫码关注云+社区

领取腾讯云代金券