JDK1.8源码(二)——java.lang.Integer 类
上一篇博客我們介紹了 java.lang 包下的 Object 類,那么本篇博客接著介紹該包下的另一個(gè)類 Integer。在前面 淺談 Integer 類?博客中我們主要介紹了 Integer 類 和 int 基本數(shù)據(jù)類型的關(guān)系,本篇博客是從源碼層次詳細(xì)介紹 Integer 的實(shí)現(xiàn)。
1、Integer 的聲明
public final class Integer extends Number implements Comparable<Integer>{}Integer 是用 final 聲明的常量類,不能被任何類所繼承。并且 Integer 類繼承了 Number 類和實(shí)現(xiàn)了 Comparable 接口。 Number 類是一個(gè)抽象類,8中基本數(shù)據(jù)類型的包裝類除了Character 和 Boolean 沒有繼承該類外,剩下的都繼承了 Number 類,該類的方法用于各種數(shù)據(jù)類型的轉(zhuǎn)換。Comparable 接口就一個(gè)??compareTo 方法,用于元素之間的大小比較,下面會(huì)對(duì)這些方法詳細(xì)展開介紹。
2、Integer 的主要屬性
int 類型在 Java 中是占據(jù) 4 個(gè)字節(jié),所以其可以表示大小的范圍是?-2?31——2?31?-1即?-2147483648——2147483647,我們?cè)谟?int 表示數(shù)值時(shí)一定不要超出這個(gè)范圍了。
3、構(gòu)造方法 Integer(int)? ? Integer(String)
對(duì)于第一個(gè)構(gòu)造方法 Integer(int),源碼如下,這沒什么好說的。
1 public Integer(int var1) { 2 this.value = var1; 3 } View Code對(duì)于第二個(gè)構(gòu)造方法 Integer(String) 就是將我們輸入的字符串?dāng)?shù)據(jù)轉(zhuǎn)換成整型數(shù)據(jù)。
首先我們必須要知道能轉(zhuǎn)換成整數(shù)的字符串必須分為兩個(gè)部分:第一位必須是"+"或者"-",剩下的必須是 0-9 和 a-z 字符
1 public Integer(String s) throws NumberFormatException { 2 this.value = parseInt(s, 10);//首先調(diào)用parseInt(s,10)方法,其中s表示我們需要轉(zhuǎn)換的字符串,10表示以十進(jìn)制輸出,默認(rèn)也是10進(jìn)制 3 } 4 5 public static int parseInt(String s, int radix) throws NumberFormatException{ 6 //如果轉(zhuǎn)換的字符串如果為null,直接拋出空指針異常 7 if (s == null) { 8 throw new NumberFormatException("null"); 9 } 10 //如果轉(zhuǎn)換的radix(默認(rèn)是10)<2 則拋出數(shù)字格式異常,因?yàn)檫M(jìn)制最小是 2 進(jìn)制 11 if (radix < Character.MIN_RADIX) { 12 throw new NumberFormatException("radix " + radix + 13 " less than Character.MIN_RADIX"); 14 } 15 //如果轉(zhuǎn)換的radix(默認(rèn)是10)>36 則拋出數(shù)字格式異常,因?yàn)?到9一共10位,a到z一共26位,所以一共36位 16 //也就是最高只能有36進(jìn)制數(shù) 17 if (radix > Character.MAX_RADIX) { 18 throw new NumberFormatException("radix " + radix + 19 " greater than Character.MAX_RADIX"); 20 } 21 int result = 0; 22 boolean negative = false; 23 int i = 0, len = s.length();//len是待轉(zhuǎn)換字符串的長(zhǎng)度 24 int limit = -Integer.MAX_VALUE;//limit = -2147483647 25 int multmin; 26 int digit; 27 //如果待轉(zhuǎn)換字符串長(zhǎng)度大于 0 28 if (len > 0) { 29 char firstChar = s.charAt(0);//獲取待轉(zhuǎn)換字符串的第一個(gè)字符 30 //這里主要用來判斷第一個(gè)字符是"+"或者"-",因?yàn)檫@兩個(gè)字符的 ASCII碼都小于字符'0' 31 if (firstChar < '0') { 32 if (firstChar == '-') {//如果第一個(gè)字符是'-' 33 negative = true; 34 limit = Integer.MIN_VALUE; 35 } else if (firstChar != '+')//如果第一個(gè)字符是不是 '+',直接拋出異常 36 throw NumberFormatException.forInputString(s); 37 38 if (len == 1) //待轉(zhuǎn)換字符長(zhǎng)度是1,不能是單獨(dú)的"+"或者"-",否則拋出異常 39 throw NumberFormatException.forInputString(s); 40 i++; 41 } 42 multmin = limit / radix; 43 //通過不斷循環(huán),將字符串除掉第一個(gè)字符之后,根據(jù)進(jìn)制不斷相乘在相加得到一個(gè)正整數(shù) 44 //比如 parseInt("2abc",16) = 2*16的3次方+10*16的2次方+11*16+12*1 45 //parseInt("123",10) = 1*10的2次方+2*10+3*1 46 while (i < len) { 47 digit = Character.digit(s.charAt(i++),radix); 48 if (digit < 0) { 49 throw NumberFormatException.forInputString(s); 50 } 51 if (result < multmin) { 52 throw NumberFormatException.forInputString(s); 53 } 54 result *= radix; 55 if (result < limit + digit) { 56 throw NumberFormatException.forInputString(s); 57 } 58 result -= digit; 59 } 60 } else {//如果待轉(zhuǎn)換字符串長(zhǎng)度小于等于0,直接拋出異常 61 throw NumberFormatException.forInputString(s); 62 } 63 //根據(jù)第一個(gè)字符得到的正負(fù)號(hào),在結(jié)果前面加上符號(hào) 64 return negative ? result : -result; 65 } View Code?4、toString()? toString(int i) ? toString(int i, int radix)
這三個(gè)方法重載,能返回一個(gè)整型數(shù)據(jù)所表示的字符串形式,其中最后一個(gè)方法 toString(int,int) 第二個(gè)參數(shù)是表示的進(jìn)制數(shù)。
public String toString() {return toString(value); }public static String toString(int i) {if (i == Integer.MIN_VALUE)return "-2147483648";int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);char[] buf = new char[size];getChars(i, size, buf);return new String(buf, true); } View CodetoString(int) 方法內(nèi)部調(diào)用了 stringSize() 和 getChars() 方法,stringSize()?它是用來計(jì)算參數(shù) i 的位數(shù)也就是轉(zhuǎn)成字符串之后的字符串的長(zhǎng)度,內(nèi)部結(jié)合一個(gè)已經(jīng)初始化好的int類型的數(shù)組sizeTable來完成這個(gè)計(jì)算。
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,99999999, 999999999, Integer.MAX_VALUE };// Requires positive xstatic int stringSize(int x) {for (int i=0; ; i++)if (x <= sizeTable[i])return i+1;} View Code實(shí)現(xiàn)的形式很巧妙。注意負(fù)數(shù)包含符號(hào)位,所以對(duì)于負(fù)數(shù)的位數(shù)是 stringSize(-i) + 1。
再看 getChars 方法:
1 static void getChars(int i, int index, char[] buf) { 2 int q, r; 3 int charPos = index; 4 char sign = 0; 5 6 if (i < 0) { 7 sign = '-'; 8 i = -i; 9 } 10 11 // Generate two digits per iteration 12 while (i >= 65536) { 13 q = i / 100; 14 // really: r = i - (q * 100); 15 r = i - ((q << 6) + (q << 5) + (q << 2)); 16 i = q; 17 buf [--charPos] = DigitOnes[r]; 18 buf [--charPos] = DigitTens[r]; 19 } 20 21 // Fall thru to fast mode for smaller numbers 22 // assert(i <= 65536, i); 23 for (;;) { 24 q = (i * 52429) >>> (16+3); 25 r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... 26 buf [--charPos] = digits [r]; 27 i = q; 28 if (i == 0) break; 29 } 30 if (sign != 0) { 31 buf [--charPos] = sign; 32 } 33 } View Codei:被初始化的數(shù)字,
index:這個(gè)數(shù)字的長(zhǎng)度(包含了負(fù)數(shù)的符號(hào)“-”),
buf:字符串的容器-一個(gè)char型數(shù)組。
第一個(gè)if判斷,如果i<0,sign記下它的符號(hào)“-”,同時(shí)將i轉(zhuǎn)成整數(shù)。下面所有的操作也就只針對(duì)整數(shù)了,最后在判斷sign如果不等于零將 sign 你的值放在char數(shù)組的首位buf [--charPos] = sign;。
5、自動(dòng)拆箱和裝箱
自動(dòng)拆箱和自動(dòng)裝箱是 JDK1.5 以后才有的功能,也就是java當(dāng)中眾多的語(yǔ)法糖之一,它的執(zhí)行是在編譯期,會(huì)根據(jù)代碼的語(yǔ)法,在生成class文件的時(shí)候,決定是否進(jìn)行拆箱和裝箱動(dòng)作。
①、自動(dòng)裝箱
我們知道一般創(chuàng)建一個(gè)類的對(duì)象需要通過 new 關(guān)鍵字,比如:
Object obj = new Object();但是實(shí)際上,對(duì)于 Integer 類,我們卻可以直接這樣使用:
Integer a = 128;為什么可以這樣,通過反編譯工具,我們可以看到,生成的class文件是:
Integer a = Integer.valueOf(128);我們可以看看 valueOf() 方法
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); } View Code其實(shí)最后返回的也是通過new Integer() 產(chǎn)生的對(duì)象,但是這里要注意前面的一段代碼,當(dāng)i的值 -128 <= i <= 127 返回的是緩存類中的對(duì)象,并沒有重新創(chuàng)建一個(gè)新的對(duì)象,這在通過 equals 進(jìn)行比較的時(shí)候我們要注意。
這就是基本數(shù)據(jù)類型的自動(dòng)裝箱,128是基本數(shù)據(jù)類型,然后被解析成Integer類。
②、自動(dòng)拆箱
我們將 Integer 類表示的數(shù)據(jù)賦值給基本數(shù)據(jù)類型int,就執(zhí)行了自動(dòng)拆箱。
1 Integer a = new Integer(128); 2 int m = a;反編譯生成的class文件:
1 Integer a = new Integer(128); 2 int m = a.intValue();簡(jiǎn)單來講:自動(dòng)裝箱就是Integer.valueOf(int i);自動(dòng)拆箱就是 i.intValue();關(guān)于拆箱和裝箱的詳細(xì)介紹可以看我這篇博客。
6、equals(Object obj)方法
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false; }這個(gè)方法很簡(jiǎn)單,先通過 instanceof 關(guān)鍵字判斷兩個(gè)比較對(duì)象的關(guān)系,然后將對(duì)象強(qiáng)轉(zhuǎn)為 Integer,在通過自動(dòng)拆箱,轉(zhuǎn)換成兩個(gè)基本數(shù)據(jù)類 int,然后通過 == 比較。
7、hashCode() 方法
1 public int hashCode() { 2 return value; 3 }Integer 類的hashCode 方法也比較簡(jiǎn)單,直接返回其 int 類型的數(shù)據(jù)。
8、parseInt(String s) 和??parseInt(String s, int radix) 方法
前面通過 toString(int i) 可以將整型數(shù)據(jù)轉(zhuǎn)換成字符串類型輸出,這里通過 parseInt(String s) 能將字符串轉(zhuǎn)換成整型輸出。
這兩個(gè)方法我們?cè)诮榻B 構(gòu)造函數(shù)?Integer(String s) 時(shí)已經(jīng)詳細(xì)講解了。
9、compareTo(Integer anotherInteger) 和?compare(int x, int y) 方法
1 public int compareTo(Integer anotherInteger) { 2 return compare(this.value, anotherInteger.value); 3 } View CodecompareTo 方法內(nèi)部直接調(diào)用?compare 方法:
1 public static int compare(int x, int y) { 2 return (x < y) ? -1 : ((x == y) ? 0 : 1); 3 } View Code如果 x < y 返回 -1
如果 x == y 返回 0
如果 x > y 返回 1
1 System.out.println(Integer.compare(1, 2));//-1 2 System.out.println(Integer.compare(1, 1));//0 3 System.out.println(Integer.compare(1, 0));//1 View Code那么基本上 Integer 類的主要方法就介紹這么多了,后面如果有比較重要的,會(huì)再進(jìn)行更新。
?
參考文檔:https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
?
作者:YSOcean 出處:http://www.cnblogs.com/ysocean/ 本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意不能轉(zhuǎn)載,否則保留追究法律責(zé)任的權(quán)利。總結(jié)
以上是生活随笔為你收集整理的JDK1.8源码(二)——java.lang.Integer 类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 申请Let's Encrypt通配符HT
- 下一篇: 细说awk