在需要将一个数字类型变量转换得到String 时,经常使之与空字符串连接:
int i = 100 ;
String str = i+"" ;
另外, 还有:
String str1 = String.valueOf(i) ;
String str2 = Integer.toString(i) ;
两种语法。 其中String.valueOf 会调用Integer.toString(i,10)。 因此这里只讨论 i+"" 与 String.valueOf 的差异。
首先,
int i = 223344 ;
String str = i + "" ;
反编译得到的字节码是:
0: ldc #2; //int 223344
2: istore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
10: iload_1
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
14: ldc #6; //String
16: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
而
int i = 223344 ;
String str2 = String.valueOf(i);
得到的是:
0: ldc #2; //int 223344
2: istore_1
3: iload_1
4: invokestatic #3; //Method java/lang/String.valueOf:(I)Ljava/lang/String;
7: astore_2
彻底搞清二者的区别势必要进一步最终各自对应方法的具体实现。
其中,String.valueOf 会调用Integer.toString() , 后者将数字的每一位拆分开放到[C里,然后构造一个字符串。 这里有两次对象创建,一次 new char[] ,一次new String 。 后者会copy一份[C的内容(这点从api文档可以得知)。
而StringBuilder也是包装了一个[C , sb.toString 也是new String调用,但是包装[C后的sb对象笔[C要大,这样创建对象使用内存上就多了。 并且 i+"" ,是 append(int) 与 append(String)两次调用,前者也是使用了Integer的getChars相关方法得到[C。
用段简单的代码测试两种用法:
public static void main(String [] a){
int repeate = 100000000 ;
String str = null;
long start = System.currentTimeMillis();
for(int i=0;i<repeate;i++)
str = i + "" ;
long t1 = System.currentTimeMillis();
for(int i=0;i<repeate;i++)
str = Integer.toString(i);
System.out.println("t1:" + (t1 - start) +" t2:" + (t2- t1));
}
输出:
t1:20811 t2:10124 。
鉴于运算次数如此之大, 差别在同一个量级,还不算大。
另外, 通过观察gc情况, 前者明显比后者要频繁(当然这跟分配内存大小有关),也就是说明其内存消耗更大。
结论是, 如果你有代码洁癖,那么使用Integer.toString (或者String.valueOf)吧。
另外,如果习惯了 i + "" 这样的语法也基本不用纠结