Map存入的数据丢失类型任意

时间:2024-04-04 14:03:26

Map存入的数据丢失类型任意

发现问题:Map存入的数据丢失类型

  • 经常会使用 Map<String,Object> 来用于存储键值对的数据,由于我们使用 Object 类型来接收数字,但是有些时候会出现map并不知道我们传入的是 Long 还是 Integer 。也就是出现数据类型丢失的问题

接下来尝试复现bug:

  • 准备一个Map<String,Object> ,并将Long对象存入

  • 取出该Long对象,并用instance of 判断该对象类型

  • 经过测试发现,正常的存取并不会出现该问题是正常的情况

  • 尝试使用JSON将map序列化,转换后进行测试

  • 测试发现,BUG成功复现了,数据类型丢失了,Long类型被降级为INT

  • 测试的Demo代码如下:

  • package com.test;
    
    import com.alibaba.fastjson.JSON;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class TestMain {
    
        public static void main(String[] args) {
            Map<String , Object> map = new HashMap<>();
            Long dataLong = 123456L;
            map.put("test",dataLong);
            System.out.println(JSON.toJSONString(map));
            Object test = map.get("test");
            System.out.println("测试一下正常使用map,是否会导致存入了Long类型丢失转换为int:");
            System.out.println(test instanceof Integer);
    
            // ========
    
    
            Object mapp = JSON.parse(JSON.toJSONString(map));
            Map<String , Object> objectMap = (Map<String , Object>) mapp;
            System.out.println(objectMap.toString());
            Object objectTest = objectMap.get("test");
            System.out.println("序列化存储map,是否会导致存入了Long类型丢失转换为int:");
            System.out.println(objectTest instanceof Integer);
    
        }
    }
    
  • 输出结果如下:

  • image-20230223214504915

问题分析

  • 不难发现,两次的map其实对应的JSON字符串样式的一直的,但是在从字符串转换为map时丢失了数据类型。
  • 在进行转换时, Map 会根据我们传入的数值的大小来判断。也就是说如果你传入的数值的大小是在Integer.MIN_VALUE、 Integer.MAX_VALUE 之间,Map 就认为是 Integer 类型,如果超过了这个范围就认为是 Long 类型。
  • 在实际开发中,还挺经常遇到这种情况的,开发初期理所当然的当成int类型处理和转换,会随着数据位数的增加在中后期就报错,到时候属于是隐性BUG了。
  • 要解决也很简单,需要我们对数据类型的转换熟悉再熟悉。

问题解决

  • 解决的思路很简单,就是确保无论map中提取到的对象是int还是long或其他,都要统一转换为我们想要的long类型,在做处理的时候就是**将这个对象也先序列化,再转换,**这样就可以确保数据类型不会丢失,达到预期。

  • // 不直接强转先用 Object 接收
    Object number = map.get("number");
    // 下面两种二选一
    Long longNumber = Long.valueOf(number.toString());
    Long longNumber = Long.valueOf(String.valueOf(number));
    
包装类型不能直接强转
  • // 强转会报如下错误
    // class java.lang.Integer cannot be cast to class java.lang.Long 
    Integer number = 10;
    // 这样的强转是不对的
    Long number2 = (Long)number;
    
正确的转换方式
  • // int 转 long
    int a = 10;
    long b = (long)a;
    // long 转 int
    long a = 10L;
    int b = (int)a;
    
    
  • Integer a = 10;
    Long b = a.longValue();
    // Long 转 Integer
    Long a = 10L;
    Integer b = a.intValue();
    // 或者
    Long a = 10L;
    Integer b = Math.toIntExact(a);
    

相关文章