Summary of the problem: The data stored in the Map is lost in any type

Found the problem: the type of data loss stored in the Map

Map<String, Object> is often used to store key-value pair data, because we use the Object type to receive numbers, but sometimes the map does not know whether we pass in a Long or an Integer. That is, the problem of data type loss occurs.

Next try to reproduce the bug:

  1. Prepare a Map<String, Object>, and store the Long object in
  2. Take out the Long object and use instance of to judge the object type
    • After testing, it is found that this problem does not occur during normal access.
  3. Try to use JSON to serialize the map and test it after conversion
    • The test found that the bug was successfully reproduced, the data type was lost, and the Long type was downgraded to INT

The demo code for the test is as follows:

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);

    }
}

The output is as follows:

image-20230223214504915

problem analysis

It is not difficult to find that the two maps actually correspond to the same JSON string style, but the data type is lost when converting from a string to a map.

When converting, Map will judge based on the size of the value we pass in. That is to say, if the size of the value you pass in is between Integer.MIN_VALUE and Integer.MAX_VALUE, Map will consider it as Integer type, and if it exceeds this range, it will consider it as Long type.

In actual development, this kind of situation is quite often encountered. In the early stage of development, it is taken for granted that the int type is processed and converted, and an error will be reported in the middle and late stages as the number of data bits increases. At that time, it is a hidden bug.

It is also very simple to solve, we need to be familiar with the conversion of data types.

problem solved

The solution is very simple. It is to ensure that no matter whether the object extracted from the map is int or long or other, it must be uniformly converted to the long type we want. When doing processing, it is ** to serialize this object first. Then convert, **This way you can ensure that the data type will not be lost and meet expectations.

// 不直接强转先用 Object 接收
Object number = map.get("number");
// 下面两种二选一
Long longNumber = Long.valueOf(number.toString());
Long longNumber = Long.valueOf(String.valueOf(number));

Thinking: data type conversion

By the way, review the knowledge points

1. The package type cannot be directly forced

// 强转会报如下错误
// class java.lang.Integer cannot be cast to class java.lang.Long 
Integer number = 10;
// 这样的强转是不对的
Long number2 = (Long)number;

2. The correct conversion method

Conversion between primitive data types
// int 转 long
int a = 10;
long b = (long)a;
// long 转 int
long a = 10L;
int b = (int)a;
Conversion between package types
Integer a = 10;
Long b = a.longValue();
// Long 转 Integer
Long a = 10L;
Integer b = a.intValue();
// 或者
Long a = 10L;
Integer b = Math.toIntExact(a);

Reference blog : The original blog is well written

Guess you like

Origin blog.csdn.net/Xcong_Zhu/article/details/129191179