深入理解Java中的String

69 阅读1分钟

String为何不可变

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
	//...
}

当new String("ab")时,创建了几个对象

从字节码文件中我们可以看出,它首先是在堆中创建了ab,接下来检查字符串常量中是否有ab,如果没有,就在常量池中新建一个ab(注意此时两者的地址是不一样的)。接下来我们来探究一个老生常谈的问题

String a=new String("a")+new String("b");  
String x="ab";  
String c=a.intern();  
  
System.out.println(System.identityHashCode(a));//1157740463  
System.out.println(System.identityHashCode(c));//1379435698

在这里借用一张图

image.png 如果有x="ab"这一操作时,我们会首先将ab放到常量池中(由于前一步并没有在常量池中产生ab)所以a!=c,而如果我们不加这一行代码时,在JDK1.7以后,由常量池中没有ab我们会将a的地址放到c中,此时a==c,而在1.7以前,我们时复制了一个匿名对象在放入常量池的,所以a!=c

字符串的+

Java 语言本身并不支持运算符重载,“+”和“+=”是专门为 String 类重载过的运算符,也是 Java 中仅有的两个重载过的运算符。 不过,在循环内使用“+”进行字符串的拼接的话,存在比较明显的缺陷:编译器不会创建单个 StringBuilder 以复用,会导致创建过多的 StringBuilder 对象。不过,使用 “+” 进行字符串拼接会产生大量的临时对象的问题在 JDK9 中得到了解决。在 JDK9 当中,字符串相加 “+” 改为了用动态方法 makeConcatWithConstants() 来实现