String字符串的相关问题

79 阅读2分钟

1. String s = "a" + "b";

这个问题的解释如下,这个语句可以直接相当于s = "ab";这个是在编译期间就已经优化好了,不会再做其他的拼接什么的操作。或者说在.java文件编译的时候,常量池中就已经有了“ab”,“a”,"b"这三个对象了。因此,看似拼接的“+”操作,实际没做其他的什么事情。比较唬人!

2.String a = s + “c”;

注意这个代码里面会涉及其他的操作,不是那么简单的拼接了。看如下代码。

String b = "b";
String c = "a" + b;

在这个代码中,可以看出在第二行开始进行拼接的时候,是new了一个StringBuilder对象,然后进行append("c")操作,最终进行了一个toString()操作。

9 new #5 <java/lang/StringBuilder>
12 dup
13 invokespecial #6 <java/lang/StringBuilder.<init> : ()V>
16 ldc #3 <a>
18 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
21 aload_3
22 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
25 invokevirtual #8 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
28 astore 4

在这个字节码文件中的1、2、3。这三行代码就是以前在创建对象的三个步骤,这个地方说明创建了一个StringBuilder对象,只有一直到代码中的第8行。完成了toString()操作。返回了一个String类型的对象并完成了第9行的存储。
因此,扩展一下,如果在字串的拼接中有变量存在,则可以认为,存在StringBuilder的append,以及最后的toString操作。
特殊地

final String b = "b";
final String a = "a";
String c = a + b;

在这个地方相当于1中的操作,直接在字符串常量池中就有了“ab”这个字串。直接在常量池中拿就行了。不用拼接,原因是final已经表示b不再是一个变量了。

3.new String("zzw")

这个地方呢,直接可以借鉴new一个对象的发生过程。见如下字节码

 0 new #2 <java/lang/String>
 3 dup
 4 ldc #3 <aa>
 6 invokespecial #4 <java/lang/String.<init> : (Ljava/lang/String;)V>
 9 astore_1

因此就可以认为是执行了一个初始化方法把“aa”这个值赋到这个变量内部的属性里就行了。

4 String s = new String("a") + new String("b")

可以根据2,3自己进行推理。首先是new一个stringBuilder对象,之后new一个String(“a”)对象,append,之后new String("b")对象,进行append。之后执行一个toString()方法。在这个toString方法中完成String对象的init操作。因此,一共创建了6个对象,并且在字串常量池中不存在“ab”这个字符串。