1 | public final class Integer extends Number implements Comparable<Integer> |
Integer 由final修飾了,所以該類不能夠被繼承,同時 Integer 繼承了Number類,因此可以將Integer轉(zhuǎn)換成 int 、double、float、long、byte和short類型的數(shù)據(jù),另外,也實現(xiàn)了comparable接口,因此Integer類也可以進行自然排序。
構(gòu)造方法只有兩個:
1 | public Integer( int value) { |
1 | public Integer(String s) throws NumberFormatException { |
2 | this .value = parseInt(s, 10 ); |
我們主要看第二個構(gòu)造方法,傳入一個字符串,然后調(diào)用parseInt方法,接下來進入parseInt的源碼:
01 | public static int parseInt(String s, int radix) |
02 | throws NumberFormatException |
68 | if (result < limit + digit) { |
69 | throw NumberFormatException.forInputString(s); |
74 | throw NumberFormatException.forInputString(s); |
76 | return negative ? result : -result; |
這個方法中最核心的步驟是1、result *= radix; 2、result -= digit; 經(jīng)過這兩個步驟將字符串轉(zhuǎn)換成數(shù)值類型。大概流程是這樣的:
-
假如字符串"1234" 轉(zhuǎn)換成int類型,result 的初始值為0,radix默認(rèn)為10;
-
首先截取字符串的第一個字符1(這里忽略各種檢查),經(jīng)過第一步計算 result = 0*10 = 0;第二部計算 result = 0 - 1 = -1;
-
第一遍循環(huán)結(jié)束后,result 的值 變成了 -1
-
截取第二個字符 2 ,result = -1 * 10 = -10,result = -10 - 2 = -12;
-
截取第三個字符 3 ,result = -12 * 10 = -120,result = -120 - 3 = -123;
-
截取第四個字符 4 ,result = -123 * 10 = -1230 ,result = -1230-4 = -1234;
-
循環(huán)結(jié)束,此時result的值為 -1234,完成字符串向整數(shù)型的轉(zhuǎn)換,返回是取反即可。
面我將從一個面試題引出問題,然后通過閱讀源碼來解決這個問題。
01 | public static void main(String[] args) { |
06 | Integer i5 = Integer.valueOf( 100 ); |
07 | Integer i6 = Integer.valueOf( 100 ); |
08 | Integer i7 = new Integer( 100 ); |
09 | System.out.println( "i1 == i2 的結(jié)果是:" + (i1 == i2)); |
10 | System.out.println( "i3 == i4 的結(jié)果是:" + (i3 == i4)); |
11 | System.out.println( "i5 == i6 的結(jié)果是:" + (i5 == i6)); |
12 | System.out.println( "i1 == i5 的結(jié)果是:" + (i1 == i5)); |
13 | System.out.println( "i1 == i7 的結(jié)果是:" + (i1 == i7)); |
運行結(jié)果為:
2 | i3 == i4 的結(jié)果是: false |
5 | i1 == i7 的結(jié)果是: false |
我們先來看第一和第二條結(jié)果,同樣是比較兩個相同數(shù)值,為什么會有不同的結(jié)果呢?接下我將通過源碼來解釋原因。
首先,我們通過編譯獲取到class文件的字節(jié)碼

從圖中我們可以看到,在執(zhí)行 Integer i1 = 100 這條命令的時候,編譯器會調(diào)用Integer中的靜態(tài)方法 valueOf,接下來我們看看 valueOf方法是怎么實現(xiàn)的吧。
1 | public static Integer valueOf( int i) { |
2 | if (i >= IntegerCache.low && i <= IntegerCache.high) |
3 | return IntegerCache.cache[i + (-IntegerCache.low)]; |
這個代碼看起來很簡單,Integer 中有一個靜態(tài)內(nèi)部類 IntegerCache,調(diào)用該方法時首先會判斷該值是否在緩存的范圍內(nèi),如果在則直接將緩存中的數(shù)值返回,否則返回一個新對象。看到這里我們似乎已經(jīng)知道了上面的問題的答案了,接下來繼續(xù)看靜態(tài)內(nèi)部類吧
01 | private static class IntegerCache { |
02 | static final int low = - 128 ; |
04 | static final Integer cache[]; |
10 | String integerCacheHighPropValue = |
11 | sun.misc.VM.getSavedProperty( "java.lang.Integer.IntegerCache.high" ); |
12 | if (integerCacheHighPropValue != null ) { |
14 | int i = parseInt(integerCacheHighPropValue); |
19 | h = Math.min(i, Integer.MAX_VALUE - (-low) - 1 ); |
20 | } catch ( NumberFormatException nfe) { |
26 | cache = new Integer[(high - low) + 1 ]; |
29 | for ( int k = 0 ; k < cache.length; k++) |
30 | cache[k] = new Integer(j++); |
32 | assert IntegerCache.high >= 127 ; |
34 | private IntegerCache() {} |
我們知道內(nèi)部類只有在所在類實例化時才會被實例化,而且只會實例化一次,緩存操作是在靜態(tài)代碼塊中完成,也就是說在類被實例化的時候數(shù)據(jù)就已經(jīng)被緩存好了,接下使用的時候可以直接使用緩存的數(shù)據(jù)。
現(xiàn)在我們回歸到上面的問題,結(jié)果1中兩個數(shù)據(jù)均為 100,在緩存的范圍中,因此i1和i2都指向的是同一個內(nèi)存地址,因此返回true。結(jié)果2中 兩個數(shù)都是200,超出了緩存的范圍,所以直接new 出了兩個對象,因此他們的內(nèi)存地址不一致,返回結(jié)果為false;另外,使用valueOf 和 使用 = 操作符賦值時一樣的,所以結(jié)果3和結(jié)果4返回結(jié)果為 true,結(jié)果5中 是直接使用new關(guān)鍵字創(chuàng)建對象,所以他們的內(nèi)存地址肯定不一致,結(jié)果為false。
那么,現(xiàn)在問題又來了,那我怎么判斷兩個整數(shù)的大小呢?繼續(xù)看源碼
02 | * The value of the {@code Integer}. |
06 | private final int value; |
07 | public boolean equals(Object obj) { |
08 | if (obj instanceof Integer) { |
09 | return value == ((Integer)obj).intValue(); |
13 | public int intValue() { |
是的,沒錯,比較兩個數(shù)值大小時可以使用equals方法來比較,源碼中value的類型為 int型,intValue返回的也是value,因此可以判斷兩個數(shù)的大小。
1 | public static void main(String[] args) { |
4 | System.out.println( "i1 == i2 的結(jié)果是:" + i1.equals(i2)); |
補充:equals 與 == 的區(qū)別:
equals 比較的是兩個數(shù)值的大小,== 有兩種情況,如果比較的是 基本數(shù)據(jù)類型,則 == 跟equals一樣都是比較的大小,如果是引用類型或數(shù)組,則比較是內(nèi)存地址。
getChars方法:
01 | static void getChars( int i, int index, char [] buf) { |
17 | r = i - ((q << 6 ) + (q << 5 ) + (q << 2 )); |
20 | buf [--charPos] = DigitOnes[r]; |
22 | buf [--charPos] = DigitTens[r]; |
32 | q = (i * 52429 ) >>> ( 16 + 3 ); |
33 | r = i - ((q << 3 ) + (q << 1 )); |
34 | buf [--charPos] = digits [r]; |
39 | buf [--charPos] = sign; |
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。