自动包装机制Integer,与AtomicReference<Integer>的问题

从如下代码开始了解Integer的自动包装机制

 1 import java.util.concurrent.atomic.AtomicInteger;
 2 import java.util.concurrent.atomic.AtomicReference;
 3 
 4 /**
 5  * 比较方法一与方法二的区别
 6  */
 7 public class AtomicIntegerDemo {
 8 
 9     static void demo1(){
10         AtomicInteger atomicInteger = new AtomicInteger(100);
11         atomicInteger.compareAndSet(100, 200);
12         atomicInteger.compareAndSet(200, 400);
13         System.out.println(atomicInteger.get());
14     }
15 
16     /**
17      * 需要仔细了解此例输出
18      */
19     static void demo2(){
20         AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
21         atomicReference.compareAndSet(100, 200);
22         atomicReference.compareAndSet(200, 400);
23         System.out.println(atomicReference.get());
24     }
25     
26     public static void main(String[] args) {
27         demo1();
28         demo2();
29     }
30 }

此代码的输出如下:

400
200

Process finished with exit code 0

预期demo2()方法最终输出400,但结果并不是。

问题根源,自动包装机制:

 1 public final class Integer extends Number implements Comparable<Integer> {
 2     /**
 3      * The value of the {@code Integer}.
 4      *
 5      * @serial
 6      */
 7     private final int value;
 8 
 9     /**
10      * Returns an {@code Integer} instance representing the specified
11      * {@code int} value.  If a new {@code Integer} instance is not
12      * required, this method should generally be used in preference to
13      * the constructor {@link #Integer(int)}, as this method is likely
14      * to yield significantly better space and time performance by
15      * caching frequently requested values.
16      *
17      * This method will always cache values in the range -128 to 127,
18      * inclusive, and may cache other values outside of this range.
19      *
20      * @param  i an {@code int} value.
21      * @return an {@code Integer} instance representing {@code i}.
22      * @since  1.5
23      */
24     public static Integer valueOf(int i) {
25         if (i >= IntegerCache.low && i <= IntegerCache.high)
26             return IntegerCache.cache[i + (-IntegerCache.low)];
27         return new Integer(i);
28     }
29     /**
30      * Cache to support the object identity semantics of autoboxing for values between
31      * -128 and 127 (inclusive) as required by JLS.
32      *
33      * The cache is initialized on first usage.  The size of the cache
34      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
35      * During VM initialization, java.lang.Integer.IntegerCache.high property
36      * may be set and saved in the private system properties in the
37      * sun.misc.VM class.
38      */
39 
40     private static class IntegerCache {
41         static final int low = -128;
42         static final int high;
43         static final Integer cache[];
44         . . .
45     }
46 . . .
47 }

AtomicReference中对象的比较为地址的比较。对于int字面量java会进行装箱将其转换成Integer对象,调用的是Integer.valueOf方法, 看源码你就明白了,128以内的会使用缓存,同一个int字面量返回同一个对象用==比较为true,而超过128返回不是同一个对象,==为false,equal才是true。

本文结束。

原文地址:https://www.cnblogs.com/yelao/p/12592403.html