一.不可改变String
String对象是不可改变的,
查看JDK文档,发现String类中每一个看似修改String的方法,实际上都创建了一个新的String对象,而最初的String对象则丝毫未动.java传递参数的时候,传递的是引用的一个拷贝,调用时,都会复制一份引用,而引用所指向的对象,一直呆在某一单一物理位置,从未变动过.
二.重载 “+” 与 StringBuilder
String对象是不可改变的,你可以给一个String对象加任意多的别名.
String对象是只读的,所要指向它的任何引用都不可能改变它的值.so不会对其他引用产生什么卵影响.
用于String类中的”+” / “+=” 是Java中仅有的两个重载过的操作符,而java并不允许我们重载任何操作符;
public class one {
public static void main(String[] args) {
String a = "abc";
String b = "123" + a + "def" + 777;
System.out.println(b);
}
}
如上代码,可能这样工作:
String有append方法,然后返回一个新的String对象的引用,以包含连接后的字符串,然后再append , 再创建新对象.
这种方式当然行得通,但是为了生成最终的String,次方式会产生一堆需要垃圾回收的中间对象.然后发现其性能略lowBi.那么编译器真的会这样做吗?
来来~~,反编译生成的.class
javap -c one.class
这是JDK自带的工具 javap -c参数生成字节码
懂点汇编就行,,dup,invokevirtural 就是jvm上的汇编.
看好了:
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder.””:()V
10: ldc #5 // String 123
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
编译器自动引用java.lang.StringBuilder类,用以构造最终的String,为每个”+”调用一次append方法,最后调用toString方法生成最终的String并保存
三.what if 在循环里使用”+”呢
经过实验发现:
1.这样写:
String str = "";
for(int i = 0; i < num; i++)
{
str += "a";
}
javap -c
5~33是循环体, 15句创建一个StringBuilder对象
可知StringBuilder在循环体内构建,每次循环,创建新的StringBuilder
2.这样写:
StringBuilder a = new StringBuilder();
for(int i = 0; i < 10; i++)
{
a.append(i); //只有String能"+"
}
只创建一个StringBuilder类
所以以后写的时候就知道咋回事了.