一直覺得自己Java基礎還不錯,但是第一眼看到(Integer)129 == (Integer)129運算式時竟然無法立刻反映過來結果到底是true還是false,不妨先來看一下下面簡單的Java程式:
package com.csdn.test;public class Main { public static void main(String[] args) { System.out.println("(Integer)129 == (Integer)129"); System.out.println( (Integer)129 == (Integer)129); System.out.println("(Integer)127 == (Integer)127"); System.out.println((Integer)127 == (Integer)127); }}
編譯運行後,控制台輸出結果如下:
(Integer)129 == (Integer)129false(Integer)127 == (Integer)127true
如果平時對Java基礎關注比較少,可能有兩三年經驗的Java程式員也沒辦法解釋為什麼會有這種差異,筆者也是在網上查了一些資料才搞清楚來龍去脈。
要弄明白這個問題,首先要熟練掌握Java自動裝箱、拆箱相關的知識,Java中的自動裝/拆箱發生在運算操作和比較操作時,例如:
Integer a = 10;a = a + 10; //1.拆箱為int類型 2.計算 a+10 3.把20裝箱為Integer類型.System.out.print(a > 10); //1.把a拆箱為int類型 2. 然後比較
使用==進行比較時,情況如下:
如果==兩邊都是裝箱類型,則比較引用是否指向堆記憶體中的同一個對象。
如過==兩邊有一邊是裝箱類型,另外一邊是基本類型,則把裝箱類型拆箱為基本類型,然後進行比較。例如:
Integer a = new Integer(129);Integer b = new Integer(129);System.out.println(a == b); // 比較參考型別,返回falseSystem.out.println(a == 129); // a進行拆箱,基本類型比較,返回true
問題就在於,運算式(Integer)127 == (Integer)127和(Integer)129 == (Integer)129的值為什麼不同呢。
我們不妨看一下java.lang.Integer類的源碼,如下:
/* * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.lang;import java.lang.annotation.Native;/** * The {@code Integer} class wraps a value of the primitive type * {@code int} in an object. An object of type {@code Integer} * contains a single field whose type is {@code int}. * * <p>In addition, this class provides several methods for converting * an {@code int} to a {@code String} and a {@code String} to an * {@code int}, as well as other constants and methods useful when * dealing with an {@code int}. * * <p>Implementation note: The implementations of the "bit twiddling" * methods (such as {@link #highestOneBit(int) highestOneBit} and * {@link #numberOfTrailingZeros(int) numberOfTrailingZeros}) are * based on material from Henry S. Warren, Jr.'s <i>Hacker's * Delight</i>, (Addison Wesley, 2002). * * @author Lee Boynton * @author Arthur van Hoff * @author Josh Bloch * @author Joseph D. Darcy * @since JDK1.0 */public final class Integer extends Number implements Comparable<Integer> { ... ... private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} } ... ...}
這裡只截取了一部分關鍵代碼,如上面代碼所示,Integer類只對-128~127之間的對象做了緩衝,(Integer)127 == (Integer)127兩邊裝箱後,實際指向堆記憶體中同一個對象,(Integer)129 == (Integer)129,裝箱為參考型別後,沒有做緩衝,指向堆記憶體中不同對象,所以比較結果為false。