jvm底层造成的 “类型擦除” 的解决方案

本文介绍了Java中‘类型擦除’问题,即编译后的字节码文件不包含泛型类型信息,JVM会擦除封装对象类型,运行时可能出现类型转换异常。作者通过Debug发现问题,提出解决方案:先转成Object,再转成json字符串,最后用JSONObject.parseObject()转成所需对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

“类型擦除”的解决方案及原因

今天是我第一次遇到这个 ‘类型擦除’ 的情况,请教了有丰富的Java开发经验的同事,他告诉我说,是JVM底层对我们封装的对象类型进行了擦除,把我们的类型替换了。

产生原因
Java在编译后的字节码(.class)文件中是不包含泛型中的类型信息的,使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这就是类型擦除。如在代码中定义的List<Object>和List<String>等类型,在编译之后都会变成List,JVM看到的只是List。

当JVM擦除了我们原本封装的对象时,我们在运行的时候会发生异常,报错为:java.lang.ClassCastException 类型转换异常
类型擦除
大家可以看一下我的对象的封装:
把 UserInfo 封装到 map 里

    @RequestMapping("verify/{token}")
    public Map<String, Object> verify(@PathVariable("token") String token){
        UserInfo userInfo = userService.verify(token);
        HashMap<String, Object> map = new HashMap<>();
        map.put("user",userInfo);
        return map;
    }

在这里把从map中取出来

        String token = getToken(request);
        Map<String, Object> map = null;
        if (StringUtils.isNotEmpty(token)) {
            map = userFeignClient.verify(token);
        }
        if (null != map) {
            //已登录,并且把用户信息放到,放行
            UserInfo user = (UserInfo) map.get("user");
            Long userId = user.getId();
            request.mutate().header("userId",userId+"").build();
            exchange.mutate().request(request);

            return chain.filter(exchange);
        }

在取的时候发生了“类型擦除”,报错了:java.lang.ClassCastException : java.util.LinkedHashMap cannot be cast to com.atyunli.gmall.model.user.UserInfo

于是我Debug启动查看:
类型擦除的debug图片
实际上,value应该是我的UserInfo对象。

解决方案

发生类型擦除之后,就把JVM更改的类型转换成自己需要的类型就可以了。可以先把它转成Object 类型,因为它是所有类的父类JVM不可能对它进行封装,再把 Object 转换成 json字符串,把json字符串 转换成 我们需要的类型的对象,利用JSONObject.parseObject()这个方法。
总结:【先转成 Object -> json字符串 -> JSONObject.parseObject() 方法转成我们需要的对象】

这是我更改完的代码,其实就是把value的类型转换成我们自己需要的类型就可以了。

        if (null != map) {
           //先用object
            Object user = map.get("user"); 
            //在将object转化为string
            String userString = JSON.toJSONString(user );  
            // 再将string转化为UserInfo
            UserInfo userInfo = JSONObject.parseObject(userString, UserInfo.class);
            Long userId = userInfo.getId();
            
            request.mutate().header("userId",userId+"").build();
            exchange.mutate().request(request);

            return chain.filter(exchange);
        }

总结:
先转成 Object -> json字符串 -> JSONObject.parseObject() 方法转成我们需要的对象

即使每天忙忙碌碌,也不能忘记留下美好的瞬间,也不能忘记要学习,一点点积累。一起努力学习吧,成为更优秀的程序媛~~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值