天天看點

java.lang.Integer源碼精讀(二)轉載請注明出處

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