Java中(Integer)127 == (Integer)127和(Integer)129 == (Integer)129表達式結果差異分析

一直覺得自己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)129
false
(Integer)127 == (Integer)127
true

如果平時對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); // 比較引用類型,返回false
System.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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章