The "pit" brought by packing and unpacking

  As we all know, java has a great mechanism for the use between primitive types and reference types, which is our autoboxing and unboxing.
  But sometimes boxing and unboxing can bring us some unexpected pits! !

Just use a simple example as a demonstration:
look at the code and think about the output!

  @Test
    public void go1(){
        Integer a = 1 ;
        Integer b = 2 ;
        swap(a,b);
        System.out.println("a = "+ a + ", b = " + b);
    }

    private void swap(Integer n1, Integer n2) {
        Integer temp;
        temp = n1 ;
        n1 = n2;
        n2 = temp;
    }

This code that seems to swap the values ​​of two variables, the execution result value is not swapped.
This is because:

The variables a, b, n1, n2, and temp are all in the stack memory, so the result after execution, the value pointed to by a, n2, temp is 1, the value pointed to by b, n1 is 2, and the value we get is the value corresponding to a and b, so it is still 1, 2

At this time, we look at the Integer source code and find that the variable of the boxing operation is value, which is a private, final type variable.
We can operate it through reflection.

      try {
            Field field = Integer.class.getDeclaredField("value"); // 反射获取对象域
            field.setAccessible(true); // 设置私有成员变量为可操作
            int temp = n1.intValue();
            field.set(n1,n2); 
            field.set(n2,temp);
        } catch (Exception e) {
            e.printStackTrace();
        }

At this time, it is found that the execution result is a=2, b=2, and there is no exchange. After looking at the source code in detail, I found that it was caused by IntegerCache.

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

For numbers between [-128, 127], it will be searched in the IntegerCache. If the IntegerCache is not updated, then our search is the value stored last time. That is, if the number in front of us is no longer in this range, then the exchange will not affect it. In that case, the corresponding position of the IntegerCache has not changed. take the value we want

If we want to be more accurate and avoid these situations,
we can do manual boxing instead of automatic boxing, and the elements of IntegerCache will not affect

     Field field = Integer.class.getDeclaredField("value"); // 反射获取对象域
     field.setAccessible(true); // 设置私有成员变量为可操作
     int temp = n1.intValue();
     field.set(n1,n2); 
     field.set(n2,new Integer(temp));

In this way, after manual boxing, you can guarantee that the exchange result is 100% successful!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325750119&siteId=291194637