Integer
- Integer是int的包裝類而int是一種基本數(shù)據(jù)類型。
- Integer是面向?qū)ο蟮?,所以必須?shí)例化。
- Integer是對象的引用。int則是存儲(chǔ)數(shù)據(jù)。
類圖

1.png
public final class Integer extends Number implements Comparable<Integer> {
//
}
-
final修飾 Integer類沒有子類,類中方法默認(rèn)都是final(final方法不能被子類覆蓋) -
Integer繼承了Number類則可使用Number類中方法 -
Integer實(shí)現(xiàn)了Comparable接口,所以實(shí)現(xiàn)了compareTo方法。
屬性
private屬性
//真正存儲(chǔ)int值
private final int value;
//序列化相關(guān),Integer實(shí)現(xiàn)了 Serializable
@Native private static final long serialVersionUID = 1360826667806852920L;
public屬性
//int 最小值
@Native public static final int MIN_VALUE = 0x80000000;
//int 最大值
@Native public static final int MAX_VALUE = 0x7fffffff;
//int
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
//int bit 位數(shù)
@Native public static final int SIZE = 32;
//int byte 位數(shù)
public static final int BYTES = SIZE / Byte.SIZE;
構(gòu)造方法
public Integer(int value) {
this.value = value;
}
//根據(jù)string參數(shù)構(gòu)造新Integer對象
public Integer(String s) throws NumberFormatException {
// 10 string轉(zhuǎn)int默認(rèn)為10進(jìn)制
this.value = parseInt(s, 10);
}
常見方法
parseInt()
返回一個(gè)int基本數(shù)據(jù)類型
//返回一個(gè)十進(jìn)制的int
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
//返回一個(gè)指定進(jìn)制的int
//該方法會(huì)拋出NumberFormatException
// 1. 字符串參數(shù)為null
// 2. radix 小于 Character.MIN_RADIX 或者大于 Character.MAX_RADIX
// 3. 字符串不是int類型數(shù)據(jù)
// 4. 指定進(jìn)制無法表達(dá)字符串
public static int parseInt(String s, int radix) throws NumberFormatException{
}
valueOf()
返回一個(gè)
Integer對象
// 返回一個(gè)十進(jìn)制Integer
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
// 返回一個(gè)指定進(jìn)制Integer
public static Integer valueOf(String s, int radix) throws NumberFormatException {
// parseInt()
return Integer.valueOf(parseInt(s,radix));
}
// 內(nèi)部類 Integer 緩存
public static Integer valueOf(int i) {
// 如果 i 在 IntegerCache 之間,則返回緩存中取出。
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// 默認(rèn)最大緩存值
int h = 127;
// 讀取設(shè)置的最大緩存值
String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
// 設(shè)置最大值小于127 則最大值為默認(rèn)值 127
// 設(shè)置最大值為Integer.MAX_VALUE 則最大值為 Integer.MAX_VALUE - 128 - 1
i = Math.max(i, 127);
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// 傳入的數(shù)值不能解析為int,忽略。最大值為默認(rèn)值 127
}
}
high = h;
// 初始化緩存數(shù)組,長度為 127 + 128 + 1
cache = new Integer[(high - low) + 1];
//循環(huán)初始化 Integer 對象,并放入緩存數(shù)組
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// assert 斷言關(guān)鍵字
assert IntegerCache.high >= 127;
}
// 空構(gòu)造
private IntegerCache() {}
}
valueOf(String s)與valueOf(String s, int radix)這兩個(gè)將字符串轉(zhuǎn)換為Integer對象的方法實(shí)現(xiàn)很簡單。主要是涉及到緩存內(nèi)部類的`方法。
Integer a = 10; //this is autoboxing Integer b = Integer.valueOf(10); //under the hood當(dāng)程序使用第一次使用
Integer.valueOf()是則會(huì)緩存 -127 到 128 到IntegerCache.cache數(shù)組中(緩存的是Integer對象)。注意:構(gòu)造函數(shù)不會(huì)使用緩存。
Integer a = 10;自動(dòng)裝箱編譯后Integer b = Integer.valueOf(10);所以當(dāng)初始化Integer對象時(shí)優(yōu)先使用
Integer a = 10;
設(shè)置最大緩存值方式
-Djava.lang.Integer.IntegerCache.high=1000
-XX:AutoBoxCacheMax=1000
例子
public static void main(String[] args) {
Integer integer1 = 100; // 無緩存,Integer.valueOf(100); new Integer() 放入緩存。
Integer integer2 = 100; // 緩存中讀取。同一個(gè)Integer對象
Integer integer3 = new Integer(100); // 構(gòu)造函數(shù)不會(huì)使用緩存
if(integer1 == integer2){
System.out.println("integer1 == integer2");
}else{
System.out.println("integer1 != integer2");
}
if(integer1 == integer3){
System.out.println("integer1 == integer3");
}else{
System.out.println("構(gòu)造函數(shù)不會(huì)使用緩存");
System.out.println("integer1 != integer3");
}
if(integer2 == integer3){
System.out.println("integer2 == integer3");
}else {
System.out.println("構(gòu)造函數(shù)不會(huì)使用緩存");
System.out.println("integer2 != integer3");
}
Integer integer5 = 300; // 緩存默認(rèn)緩存 -127 到 128
Integer integer6 = 300; // 超出緩存
if(integer5 == integer6){
System.out.println("integer5 == integer6");
}else{
System.out.println("integer5 != integer6");
}
}

IntegerCache1.png

IntegerCache2.png
decode()
//接受十進(jìn)制、十六進(jìn)制、八進(jìn)制字符串,返回Integer對象
//通過截取字符串獲取進(jìn)制。然后調(diào)用valueOf()
public static Integer decode(String nm) throws NumberFormatException {}
最終調(diào)用
valueOf()方法,故而使用緩存。
getInteger()
// 根據(jù)key讀取系統(tǒng)屬性值。并轉(zhuǎn)為Integer對象
public static Integer getInteger(String nm) {
return getInteger(nm, null);
}
// 如果系統(tǒng)屬值不存在則返回默認(rèn)值 val
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 {
//讀取系統(tǒng)屬性
v = System.getProperty(nm);
} catch (IllegalArgumentException | NullPointerException e) {
}
//系統(tǒng)屬性不存在則返回 val
if (v != null) {
try {
return Integer.decode(v);
} catch (NumberFormatException e) {
}
}
return val;
}
最終調(diào)用
valueOf(),故而使用緩存。
toString()
public static String toString(int i) !
//i為最小值直接返回
if (i == Integer.MIN_VALUE)
return "-2147483648";
// 返回整數(shù) i 位數(shù)
// ① 如果 i 為負(fù)數(shù) 則轉(zhuǎn)為正整數(shù)。前方代碼 i 為最小值是轉(zhuǎn)為正整數(shù)會(huì)溢出。
// ② 假設(shè) i 等于 10 則 9 < x < 99 。i 循環(huán)到 1 ,返回 i + 1 ,10 為2位數(shù)。
// ③ 假設(shè) i 等于 -10 ,+1 是標(biāo)示負(fù)號(hào)。-10 為3位數(shù)
// 設(shè)計(jì)真精妙啊
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
// 創(chuàng)建一個(gè)位數(shù)長度的char數(shù)組
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf, true);
}
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// ② 假設(shè) i 等于 10 則 9 < x < 99 。i 循環(huán)到 1 ,返回 i + 1 ,x 位數(shù) 2 。
static int stringSize(int x) {
// i ++ 進(jìn)行無限循環(huán)
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
// i 參數(shù),index i 位數(shù),buf index 長度的char數(shù)組
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Generate two digits per iteration
// 當(dāng) i 大于等于 65536 時(shí),每循環(huán)一次將 i 最后兩位存到 buf 數(shù)組中
while (i >= 65536) {
// 除法 假如 i 為 65536 q = 655
q = i / 100;
// 相當(dāng)于 r = i - (q * 100);
// r = 36
r = i - ((q << 6) + (q << 5) + (q << 2));
//將i設(shè)置為取出 最后兩位的數(shù)字
i = q;
//從數(shù)組中獲取兩位char數(shù)值存入buf
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// 當(dāng) i 小于 65536 時(shí) 循環(huán)剩余位 存到 buf 數(shù)組 中
// 以上代碼將 65536 最后兩位存入 buf 后,i = 655
for (;;) {
// 相當(dāng)于 q = i / 10。此時(shí) q = 65
q = (i * 52429) >>> (16+3);
// 相當(dāng)于 r = i-(q*10) 。此時(shí) r = 5
r = i - ((q << 3) + (q << 1));
// 將 i 最后一位存入 buf
buf [--charPos] = digits [r];
// 設(shè)置 i 為剩余 數(shù)字,然后下次循序
i = q;
// i == 0 循環(huán)結(jié)束,將所有數(shù)字拆分存入 buf 中
if (i == 0) break;
}
if (sign != 0) {
//存入負(fù)號(hào)
buf [--charPos] = sign;
}
// 36 位是 3
// 36 / 10 結(jié)果是 3
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',// 0 - 9
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',// 10 - 19
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',// 20 - 29
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',// 30 - 39
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',// ...
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
// 36 位 取出是 6。
// 36 % 10 余數(shù) 6
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 0 - 9
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 10 - 19
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 20 - 29
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 30 - 39
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// ...
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
}
代碼上方基本上每一步的注釋都有寫,debug幾次就好了。
int i = 65536;
int q = i / 100;
int r = i - ((q << 6) + (q << 5) + (q << 2));
System.out.println(i);
System.out.println(r);
System.out.println("r = "+ i % 100);
上方代碼是從
getChars()當(dāng)i >= 65536后的一段代碼,發(fā)現(xiàn)使用了眾多的位運(yùn)算得到的結(jié)果其實(shí)和除法求余是一樣的。使用位運(yùn)算的原因就是要比直接乘除效率要高
其他基本類型
Byte
基本和Integer大同小異。
- 同樣是
final修飾 - 繼承了
Number實(shí)現(xiàn)了Comparable
parseByte()
public static byte parseByte(String s, int radix) throws NumberFormatException {
//將字符串轉(zhuǎn)為 int
int i = Integer.parseInt(s, radix);
// 如果超出 byte 范圍 拋出異常
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value out of range. Value:\"" + s + "\" Radix:" + radix);
// 向下轉(zhuǎn)換
return (byte)i;
}
valueOf()
public static Byte valueOf(byte b) {
final int offset = 128;
//同樣是從內(nèi)部緩存類中讀取
return ByteCache.cache[(int)b + offset];
}
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
// 默認(rèn)緩存 -128 到 127 數(shù)字
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
Short
參考Byte和Integer
Long
參考Byte和Integer