Integer轉String
Integer轉String的場景我們在工作中會遇到很多,我們今天來分析下有哪些方法,這些方法分別是怎麼實現的,有什麼區別。
我們首先會想到的是型別強轉,格式如:(String)Integer。
我們發現idea中編寫不通過,報錯:cannot cast 'java.lang.Integer' to 'java.lang.String'。
第二種方式呼叫Object.toString()方法。toString()方法是超類Object提供的方法,Integer肯定也含有該方法, 不過Integer對這個方法進行了重寫。我們先來執行Integer.toString()方法,然後再來具體分析該方法。
public static void main(String[] args){
Integer var = new Integer(10);
String str = var.toString();
System.out.println(str);
}
執行結果為10,沒問題。我們先來看下Object.toString()方法。
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } public native int hashCode();
Integer重寫了Object.toString()方法。
private final int value; @Native public static final int MIN_VALUE = 0x80000000; @Native public static final int MAX_VALUE = 0x7fffffff; public String toString() { //通過Integer類的成員變數value去獲取String值 return toString(value); } public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; //如果i是正整數,返回這個數是幾位數,如果是負數,取負數的絕對值位數加一,比如是-23,size為3 int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //根據Integer的位數,建立一個該位數大小的char陣列 char[] buf = new char[size]; //獲取Integer值對應的char陣列 getChars(i, size, buf); //通過new String()構造方法將char陣列轉換為String return new String(buf, true); } //x小於等於9,返回1 //x小於等於99,返回2 //按此規律返回x是幾位數 //如果x是負數,返回1 static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) return i+1; } final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; //通過參照碼錶digits,將Integer i的每一位都放到char陣列中 static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; //如果i小於0,字元前面加負號,i取絕對值 if (i < 0) { sign = '-'; i = -i; } // Generate two digits per iteration while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { buf [--charPos] = sign; } } final static char[] digits = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' };
通過研究Integer的原始碼我們發現Integer轉String的主要思路是先獲得Integer的位數,如果是負數,就是這個數的絕對值的位數加一(負號佔一位),然後根據位數建立一個char陣列,將Integer的每一位都放到char陣列中,最後通過String的new String(Char[] char,boolean share)構造方法建立字串。
第三種方式是String類提供的靜態方法String.valueOf(Integer i )。
Integer var = new Integer(10);
String str = String.valueOf(var);
看下String類中String.valueOf(Integer i )的底層原始碼。
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
我們看到底層還是呼叫的Integer.toString()方法。這裡有一點我們需要注意的是String類的valueOf()方法,如果傳入值是null,返回值是“null”,而不是null。
第四種方式Integer+""方式,就是在Integer的變數值後面加上一個空字串。
Integer var = new Integer(10);
String str = var+"";
System.out.println(str);
這個程式碼得去看位元組碼檔案分析。我們可以使用javap命令或者idea提供的jclasspath外掛檢視。檔案內容如下所示:
0 new #2 <java/lang/Integer>
3 dup
4 bipush 10
6 invokespecial #3 <java/lang/Integer.<init>>
9 astore_1
10 new #4 <java/lang/StringBuilder>
13 dup
14 invokespecial #5 <java/lang/StringBuilder.<init>>
17 aload_1
18 invokevirtual #6 <java/lang/StringBuilder.append>
21 ldc #7
23 invokevirtual #8 <java/lang/StringBuilder.append>
26 invokevirtual #9 <java/lang/StringBuilder.toString>
29 astore_2
30 getstatic #10 <java/lang/System.out>
33 aload_2
34 invokevirtual #11 <java/io/PrintStream.println>
37 return
我們發現位元組碼檔案中是建立StringBuilder,通過StringBuilder.append()方法將Integer型別的var和空字串""連線起來的,相當於下面的java流程:
Integer var = new Integer(10);
StringBuilder builder = new StringBuilder();
builder.append(var);
builder.append("");
String str = builder.toString();
System.out.println(str);
再看下builder.append(var)的底層程式碼:
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
StringBuilder的append(Object obj)方法裡是先通過String.valueOf()方法將obj轉換為String型別,然後再呼叫append方法。而String.valueOf()方法最終還是呼叫的Integer類的toString()方法。
結合三種方式我們發現最終都是落到了Integer類的toString()方法上來了,那麼我們在實際寫程式碼中遇到Integer轉String型別的時候不妨就直接呼叫Integer的toString()方法了。