java.lang.Boolean
1 public static int hashCode(boolean value) { 2 return value ? 1231 : 1237; 3 }
JDK 1.8新增一個hashCode方法,true的hashCode為1231,false的hashCode為1237, why?
https://stackoverflow.com/questions/3912303/boolean-hashcode
1 public static int compare(boolean x, boolean y) { 2 return (x == y) ? 0 : (x ? 1 : -1); 3 }
在類中定義了兩個public static final的變量,在創建Boolean對象的時候可以
1 public static final Boolean TRUE = new Boolean(true); 2 public static final Boolean FALSE = new Boolean(false);
在創建Boolean對象的時候整個項目如果都是采用valueOf方法來創建,則整個項目就都會使用的這兩個對象了。
1 public static Boolean valueOf(boolean b) { 2 return (b ? TRUE : FALSE); 3 } 4 public static Boolean valueOf(String s) { 5 return parseBoolean(s) ? TRUE : FALSE; 6 }
剩下的Byte、Short、Integer、Long、Float、Double都是繼承自Number類,除此之外還有BigDecimal和BigInteger類。
下面總結下基礎數據類型的數值范圍
數據類型 | 字節 | 范圍 |
boolean | 1 | true或false |
char | 2 | 從字符型對應的整型數來划分,其表示范圍是0~65535 |
byte | 1 | -128~127 |
short | 2 | -32768~32767 |
int | 4 | -2147483648~2147483647 (-2^31 ~ 2^31-1) |
long | 8 | -9223372036854775808 ~ 9223372036854775807 |
float | 4 | -3.4E38~3.4E38 |
double | 8 | -1.7E308~1.7E308 |
java.lang.Integer
1 public static String toString(int i) { 2 if (i == Integer.MIN_VALUE) 3 return "-2147483648"; 4 int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); 5 char[] buf = new char[size]; 6 getChars(i, size, buf); 7 return new String(buf, true); 8 } 9 10 static void getChars(int i, int index, char[] buf) { 11 int q, r; 12 int charPos = index; 13 char sign = 0; 14 15 if (i < 0) { 16 sign = '-'; 17 i = -i; 18 } 19 20 // Generate two digits per iteration 21 while (i >= 65536) { 22 q = i / 100; 23 // really: r = i - (q * 100); 24 r = i - ((q << 6) + (q << 5) + (q << 2)); 25 i = q; 26 buf [--charPos] = DigitOnes[r]; 27 buf [--charPos] = DigitTens[r]; 28 } 29 30 // Fall thru to fast mode for smaller numbers 31 // assert(i <= 65536, i); 32 for (;;) { 33 q = (i * 52429) >>> (16+3); 34 r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... 35 buf [--charPos] = digits [r]; 36 i = q; 37 if (i == 0) break; 38 } 39 if (sign != 0) { 40 buf [--charPos] = sign; 41 } 42 } 43 44 final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; 45 46 // Requires positive x 47 static int stringSize(int x) { 48 for (int i=0; ; i++) 49 if (x <= sizeTable[i]) 50 return i+1; 51 } 52 53 final static char [] DigitTens = { 54 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 55 '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', 56 '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', 57 '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', 58 '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', 59 '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', 60 '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', 61 '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', 62 '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', 63 '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', 64 } ; 65 66 final static char [] DigitOnes = { 67 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 68 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 69 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 70 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 71 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 72 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 73 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 74 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 75 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 76 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 77 } ;
感覺這個toString方法實現的太巧妙了,為了減少運算真是無所不用其極,忍不住將這一整段的代碼都貼出來了。
stringSize方法是計算整個正整數x有多少個字符,如此就可以預先計算出一個整型轉換為字符數組要提前分配多少空間。這個方法的實現是通過比較大小實現的,預先定義好一個從小到大的數組sizeTable,配合下標確定size。
getChars方法是將整型i轉換為一個字符數組buf,其中index參數是整型i中包含的字符數,也即buf需要多少長度來存儲轉換后的整型。在方法中如果整型i >= 65536,則通過q = i/100; r = i - q * 100;的方式將數字拆分成兩個部分,其中r為i的前兩位。高潮來了,看他怎么實現的獲取這兩位的字符的,竟然用數組查詢的方式!當然,這是個while循環,會一直處理直到i<65536。再看下for循環中的將小於65536的數字轉換為字符數組。q = (i * 52429) >>> (16+3) 這一句其實是個除以10的操作,那為什么要用52429呢?524288 = 2^19, i * 52429 然后無符號右移19位,相當於52429/2^19 = 0.100000381,近似是等於i/10(移位運算遠比除法快,也是一種優化策略)。那為什么要選擇2^19呢?參考了下知乎的回答:java源碼中Integer.class中有個getChars方法,里面有個52429是怎么確定的?。然后我又計算了下2^20和2^21,結果竟然等於2^19,然后2^22精度就更高一些,但也沒有太大的必要了。
1 private static class IntegerCache { 2 static final int low = -128; 3 static final int high; 4 static final Integer cache[]; 5 6 static { 7 // high value may be configured by property 8 int h = 127; 9 String integerCacheHighPropValue = 10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 11 if (integerCacheHighPropValue != null) { 12 try { 13 int i = parseInt(integerCacheHighPropValue); 14 i = Math.max(i, 127); 15 // Maximum array size is Integer.MAX_VALUE 16 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 17 } catch( NumberFormatException nfe) { 18 // If the property cannot be parsed into an int, ignore it. 19 } 20 } 21 high = h; 22 23 cache = new Integer[(high - low) + 1]; 24 int j = low; 25 for(int k = 0; k < cache.length; k++) 26 cache[k] = new Integer(j++); 27 28 // range [-128, 127] must be interned (JLS7 5.1.7) 29 assert IntegerCache.high >= 127; 30 } 31 32 private IntegerCache() {} 33 } 34 35 public static Integer valueOf(int i) { 36 if (i >= IntegerCache.low && i <= IntegerCache.high) 37 return IntegerCache.cache[i + (-IntegerCache.low)]; 38 return new Integer(i); 39 }
通過IntegerCache內部類將常用的整數存儲起來,當使用valueOf的方式構造Integer對象的時候,會直接從IntegerCache中取值。IntegerCache的最小值固定為-128,最大值可以通過java.lang.Integer.IntegerCache.high設置。
java.lang.Byte
在Byte類中同樣是有個ByteCache緩存的緩存了從-128到正的127的byte,也就是byte的取值范圍都被緩存了。通過下面的valueOf就可以使用到ByteCache類中的緩存值了。
1 public static Byte valueOf(byte b) { 2 final int offset = 128; 3 return ByteCache.cache[(int)b + offset]; 4 }
Byte中的很多函數都是將byte轉換成int然后再操作的。
java.lang.Short
Short類中也同樣有個ShortCache緩存,緩存了從-128到127的整數,不過要注意short是兩個字節的。同樣的使用ValueOf可以使用緩存中的內容。
1 private static class ShortCache { 2 private ShortCache(){} 3 4 static final Short cache[] = new Short[-(-128) + 127 + 1]; 5 6 static { 7 for(int i = 0; i < cache.length; i++) 8 cache[i] = new Short((short)(i - 128)); 9 } 10 } 11 12 public static Short valueOf(short s) { 13 final int offset = 128; 14 int sAsInt = s; 15 if (sAsInt >= -128 && sAsInt <= 127) { // must cache 16 return ShortCache.cache[sAsInt + offset]; 17 } 18 return new Short(s); 19 }
1 public static short reverseBytes(short i) { 2 return (short) (((i & 0xFF00) >> 8) | (i << 8)); 3 }
在Short類中還有個reverseBytes函數,將高位字節和低位字節互換位置。不知道這樣做有什么用途。
java.lang.Long
同樣的在Long類中toString方法實現類似於Integer中的toString方法,不再贅述。
在緩存方面,Long類中同樣有個LongCache緩存類,緩存了-128L~127L的Long對象,通過valueOf可以直接獲取緩存中的類對象。
在JDK 1.8中,增加了以下幾個方法
1 // 比較兩個long 2 // @since 1.7 3 public static int compare(long x, long y) { 4 return (x < y) ? -1 : ((x == y) ? 0 : 1); 5 } 6 7 // 比較兩個unsigned long 8 // @since 1.8 9 public static int compareUnsigned(long x, long y) { 10 return compare(x + MIN_VALUE, y + MIN_VALUE); 11 } 12 13 // 除法運算,結果是除得的結果,余數采用remainderUnsigned獲得 14 // @since 1.8 15 public static long divideUnsigned(long dividend, long divisor) { 16 if (divisor < 0L) { // signed comparison 17 // Answer must be 0 or 1 depending on relative magnitude 18 // of dividend and divisor. 19 return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L; 20 } 21 22 if (dividend > 0) // Both inputs non-negative 23 return dividend/divisor; 24 else { 25 /* 26 * For simple code, leveraging BigInteger. Longer and faster 27 * code written directly in terms of operations on longs is 28 * possible; see "Hacker's Delight" for divide and remainder 29 * algorithms. 30 */ 31 return toUnsignedBigInteger(dividend). 32 divide(toUnsignedBigInteger(divisor)).longValue(); 33 } 34 } 35 36 // 除法運算,結果是余數 37 // @since 1.8 38 public static long remainderUnsigned(long dividend, long divisor) { 39 if (dividend > 0 && divisor > 0) { // signed comparisons 40 return dividend % divisor; 41 } else { 42 if (compareUnsigned(dividend, divisor) < 0) // Avoid explicit check for 0 divisor 43 return dividend; 44 else 45 return toUnsignedBigInteger(dividend). 46 remainder(toUnsignedBigInteger(divisor)).longValue(); 47 } 48 }
另外增加了sum方法,如下面的代碼,代碼中並沒有考慮溢出問題,所以謹慎調用。
1 public static long sum(long a, long b) { 2 return a + b; 3 }
java.lang.Double
1 public boolean equals(Object obj) { 2 return (obj instanceof Double) 3 && (doubleToLongBits(((Double)obj).value) == 4 doubleToLongBits(value)); 5 } 6 7 public static long doubleToLongBits(double value) { 8 long result = doubleToRawLongBits(value); 9 // Check for NaN based on values of bit fields, maximum 10 // exponent and nonzero significand. 11 if ( ((result & DoubleConsts.EXP_BIT_MASK) == 12 DoubleConsts.EXP_BIT_MASK) && 13 (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L) 14 result = 0x7ff8000000000000L; 15 return result; 16 }
在Double類中,重載了equals方法,其中的doubleToRawLongBits是個native方法。
java.lang.Float
Float源碼和Double類方法差不多。就這樣結束吧。