一道Integer面試題引發的對Integer的探究


  

面試題:

//在jdk1.5的環境下,有如下4條語句:

Integer i01 = 59;
int i02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = new Integer(59);

以下輸出結果為false的是:

A.   System.out.println(i01== i02);
B.   System.out.println(i01== i03);
C.   System.out.println(i03== i04);
D.   System.out.println(i02== i04);

1.題目中提到了,是Jdk1.5的環境。

OK,我們新建一個項目,新建一個類,把代碼復制進去。將Java Compiler設置為1.5.  關於這個版本的問題稍后再談。

2.這里有兩個數據類型,int和Integer。

   int為基本類型。

   Integer為對象類型。Integer的類聲明是這樣的:

public final class Integer extends Number implements Comparable<Integer> {

    //...

}

1、Integer類是final的,不能被繼承

 
         

2、Integer類實現了Comparable接口,所以可以用compareTo進行比較。

 
         

3、Integer繼承了Number類,所以該類可以調用longValue、floatValue、doubleValue等系列方法返回對應的類型的值。

 

3.題目中聲明了三個Integer變量,i01,i03,i04.這三種聲明方式有啥區別呢?

 

3.1 Integer i04 = new Integer(59); 做了什么?

看源碼,這個構造函數是這樣的:

    /**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

    /**
     * Constructs a newly allocated {@code Integer} object that
     * represents the specified {@code int} value.
     *
     * @param   value   the value to be represented by the
     *                  {@code Integer} object.
     */
    public Integer(int value) { this.value = value;
    }

new Integer(59)的這個操作,調用了構造函數,將59這個值,賦給了Integer的局部變量value。

 

3.2  Integer i03 = Integer.valueOf(59); //這個 Integer.valueOf 方法又做了什么??

看Integer.valueOf源碼:

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

這里,valueOf方法先判斷傳入參數的值,滿足if 條件的話,則返回cache值。

否則 new 一個Integer 返回。這里的 if中的條件 IntegerCache.high=127, IntegerCache.low=-128;從IntegerCache的類定義可以看出,IntegerCache里邊定義了一個數組cache用來存儲Integer對象,靜態塊里邊完成了數組的初始化,存入了-128到127之間的Integer對象:

    private static class IntegerCache {//這個類是 Integer 類的 靜態內部類。看這個代碼不難發現,在Integer加載之后這個內部類的cache數組里邊就初始化了-128到127之間的值 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) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low));
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

所以,對於Integer.valueOf(i)方法 , 當i在-128-127之間時返回的是緩存的Integer對象。 否則返回的是一個新的Integer對象。

這里傳遞的是59,所以返回的是cache里邊的對象。

3.3 Integer i01 = 59;// 這句話又做了什么?

我們將源碼產生的class文件反編譯發現如下:

源碼:   
public static void main(String[] args) { // TODO Auto-generated method stub Integer i01 = 59;// Integer.valueOf(59); int i02 = 59; Integer i03 = Integer.valueOf(59); Integer i04 = new Integer(59); System.out.println("i01 == i02:" + (i01 == i02)); System.out.println("i01 == i03:" + (i01 == i03)); System.out.println("i03 == i04:" + (i03 == i04)); System.out.println("i02 == i04:" + (i02 == i04)); }
反編譯之后:

public static void main(String[] args)
{
Integer i01 = Integer.valueOf(59);
int i02 = 59;
Integer i03 = Integer.valueOf(59);
Integer i04 = new Integer(59);
System.out.println("i01 == i02:" + (i01.intValue() == i02));
System.out.println("i01 == i03:" + (i01 == i03));
System.out.println("i03 == i04:" + (i03 == i04));
System.out.println("i02 == i04:" + (i02 == i04.intValue()));
}

 

 

可以發現:Integer i01=59;在反編譯過來之后是Integer.valueOf(59);

在用Integer 類型的i01和int類型的i02進行“==”比較的時候,反編譯過來的是:i01.intValue() == i02

這兩個操作分別為 自動裝箱自動拆箱。這個特性是在java1.5開始才有的。所以第一點中提到了jdk版本為1.5.

 

如果我們在eclipse/myeclipse 中將java compiler設置成1.5以下的就會無法通過編譯:

Type mismatch: cannot convert from int to Integer

 

 

通過上面的分析,這題就不難得出答案了。

i01 == i02 等價於  i01.intValue()==i02  兩個值的比較59==59   -->true;

i01 == i03 由於 59在-128到127之間,所以,i01和i03的賦值操作返回的是同一個對象。都是從chche中返回的同一個對象,對象地址相同   true;

i03 == i04 i03是來自緩存值,i04是新new的對象 ,二者不是同一個對象,所以false。

i02 == i04 和第一個類似,true。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM