引申:一个常见的String的面试题
public static void main(String[] args) { // TODO Auto-generated method stub String s1 = "Hello"; String s2 = "World"; String s3 = "Hello"+"World"; String s4 = s1+s2; String s5 = "HelloWorld"; System.out.println(s3==s5);//true System.out.println(s3.equals(s5));//true System.out.println(s4==s5);//false System.out.println(s4.equals(s5));//true }
这里我们发现同样是使用了+号运算符作为字符串的拼接,但是常量"Hello"+"World"和s1+s2的结果并不相同。
我们已经知道java在存储字符串的时候,字符串是常量;它们的值在创建之后不能更改。那么在栈中 s3 是指向了helloworld的方法区的,那么s1+s2如果没有开辟空间(一般开辟空间使用的new,但是这里并没有进行new)应该也是指向了helloworld方法区的,值应该是一样的才对,那怎么会出现2种不同的情况。
实际上,在jdk文档中已经说明了这种情况
java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder
(或 StringBuffer
)类及其 append
方法实现的。字符串转换是通过 toString
方法实现的,该方法由 Object
类定义,并可被 Java 中的所有类继承。
这里我们可以分析出其实 s1+s2是进行了new 一个StringBuilder来作为拼接的。那这样我们来反编译一下验证一下这个情况
使用Xjad反编译
这里我们看到了两个常量作为拼接的时候,编译器已经做了一次合并,所以s5和s3一模一样,s4=s1+s2,这里是new了一个StringBuilder然后append字符串s2然后转为string的。这里明显是开辟了新的堆空间。所以s4不等于s5。