从如下代码开始了解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。
本文结束。