JDK源碼精讀彙總帖
getInteger()
然後比較少用的方法getInteger,這個方法是用來傳回系統屬性(String nm)的整數值的,很容易了解。
public static Integer getInteger(String nm) {
return getInteger(nm, null);
}
public static Integer getInteger(String nm, int val) {
Integer result = getInteger(nm, null);
return (result == null) ? Integer.valueOf(val) : result;
}
public static Integer getInteger(String nm, Integer val) {
String v = null;
try {
v = System.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
if (v != null) {
try {
return Integer.decode(v);
} catch (NumberFormatException e) {
}
}
return val;
}
decode(String)
看到上面的方法調用了decode方法,這個方法與valueOf和parseInt的差別就是後者隻能分析字元串中是純數字的,而decode可以分析類似
0xff
這種。
/**
* 8進:010=>分析後為 8
* 10進:10=>分析後為 10
* 16進:#10|0X10|0x10=>分析後是 16
* 而valueOf 隻能分析純數字的String
* 注意:這裡的nm已經對應的是上面的v了,不是系統屬性的key了
*/
public static Integer decode(String nm) throws NumberFormatException {
int radix = 10;
int index = 0;
boolean negative = false;
Integer result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
char firstChar = nm.charAt(0);
// 符号處理
if (firstChar == '-') {
negative = true;
index++;
} else if (firstChar == '+')
index++;
// 進制處理
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {
index ++;
radix = 16;
}
// 以0開頭且長度不止1位的才當成8進制,否則可能就是一個0
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
if (nm.startsWith("-", index) || nm.startsWith("+", index))// 處理完前面的字元之後,還有'-'/'+',則為異常情況
throw new NumberFormatException("Sign character in wrong position");
try {
result = Integer.valueOf(nm.substring(index), radix);// 截取标志位(0x等)之後的數字,如果是Integer.MIN_VALUE,将會被傳入2147483648,會被valueOf抛出異常,是以需要在catch裡再處理
result = negative ? Integer.valueOf(-result.intValue()) : result;
} catch (NumberFormatException e) {
// If number is Integer.MIN_VALUE, we'll end up here. The next line
// handles this case, and causes any genuine format error to be
// rethrown.
// 補回'-'變成-2147483648 給Integer.valueOf再處理
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
return result;
}
hashCode()
hashCode方法,直接傳回value。
public int hashCode() {
return value;
}
equals()
equals方法比較value的比較。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
highestOneBit(int)
highestOneBit這個函數傳回的是數字i轉換成二進制後最高位1對應的數值(10000....),即2^n對應的數字
/**
* 傳回最高位的1,1後面全補0對應的數,其實就是傳回2^n
* 如果一個數是0, 則傳回0;
*如果是負數, 則傳回 -2147483648:【1000,0000,0000,0000,0000,0000,0000,0000】(二進制表示的數);
* 如果是正數, 傳回的則是跟它最靠近的比它小的2的N次方
* 原理就是不停的右移再或運算,使得i最後變成從最高位1開始後面全是1,如11111...1
*/
public static int highestOneBit(int i) {
// i右移1位在與i進行或運算,保證最高位兩位都是1:11...
i |= (i >> 1);
// 這步完成之後,最高位4位都是1,1111...
i |= (i >> 2);
// 這步完成之後,最高位8位都是1,11111111...
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
// 111...-011...到最高位的1,對應1000...
return i - (i >>> 1);
}
lowestOneBit()
然後是lowestOneBit,得到i最右邊的1對應的數值,2^n的值。
/**
* 這個方法很好了解,隻考慮最右邊1與它右邊的數,最右邊1與左邊的數無需考慮。假設i最右邊是100...0,不管1右邊幾個零,看看-i,反碼為011..1,補碼為1000,則i & -i ,1左邊的都會變成0,1右邊變成了100...0,正好得到最低位的1
*/
public static int lowestOneBit(int i) {
// HD, Section 2-1
return i & -i;
}
numberOfLeadingZeros()
然後讨論numberOfLeadingZeros,這個方法的作用是傳回參數i轉成二進制後左邊一共有多少個0。
public static int numberOfLeadingZeros(int i) {
// 如果i是零,直接傳回有32,代表二進制裡32位都是零,java裡int是4位元組
if (i == 0)
return 32;
// 後面的邏輯完全是二分法的思維,判斷i的第一個最左邊的1在哪個位置,在判斷過程中順便累加了從左邊開始0的個數,思路:先看你最左邊1在高16位還是低16位,然後再判斷你在16位中的高8位還是低8位,以此類推
int n = 1;// 0個數的計數器
// i右移16位之後有兩種情況:
// 情況1:i==0;代表左邊的1位于低16位,這樣的話n+=16代表至少有16個零了。然後把i左移16位,這樣情況1和情況2的後續處理方法就一緻了。
// 情況2:i!=0;代表左邊的1位于高16位,後續在高16位中繼續判斷
if (i >>> 16 == 0) { n += 16; i <<= 16; }
// 判斷是否在低8位,在的話,0的個數加8,然後左移8位,後續與在高8位的情況同樣處理
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
// 到這一步,所有情況都被當成是否在最高2位的情況處理了,這個時候n已經代表了0的個數
// 如果i>>>31為0,則在低1位,最左邊還有1個0,正好是n初始化為1的理由
// 如果i>>>31為1,則在高1位,最左邊沒有0了,初始化n為1會導緻多算1個0,n-1正好是0的個數
n -= i >>> 31;
return n;
}
numberOfTrailingZeros()
numberOfTrailingZeros方法也是二分法的思想,傳回最右邊0的個數。
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if (i == 0) return 32;
int n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - ((i << 1) >>> 31);
}
轉載請注明出處
java.lang.Integer源碼精讀(二)位址:
https://www.jianshu.com/p/dc50508937c6