位于java.lang包下;从概念上讲,Java字符串就是Unicode字符串的字符序列。
String的理解的重点就是对字符串是一个常量的理解;字符串是存放在常量池中。这里也是java中关于字符串常见的面试的关键点。
首先要明确的是Java中“==”都是比较的引用地址值,equals()方法是比较值是否相等(就String比较而言);
no.1
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);// true
System.out.println(s1.equals(s2));// true
此时s1和s2,都是指向常量池中的”abc“。可以自己动手画一下这段代码的内存分配图。
no.2
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
这里s1使用了new这个关键字;我们都知道使用了new这个关键字的话会在堆中开辟一个空间,所以s1这个变量是指向了堆中的内存空间,s2当然还是指向了常量池中的字符串。内存分配图大致如下:
这时s1与s2进行"=="比较的时候就是比较各自变量的引用值是否相同根据上边图上的表示,肯定是不相同的。
no.3
String s1 = "a"+"b"+"c";
String s2 = "abc";
System.out.println(s1 == s2);// true
System.out.println(s1.equals(s2));// true
这里s1在编译的过程中,优化为s1 = “abc”;所以执行s1 == s2的时候输出的是true;
String a = "a";
String b = "b";
String c = "c";
String s1 = a+b+c;
String s2 = "abc";
System.out.println(s1 == s2);// false
System.out.println(s1.equals(s2));// true
这里s1使用了字符串变量进行"+"操作,在编译期会优化为StringBuilid中append()方法操作,最后在进行StringBuilder.toString操作;可以通过StringBuilder的源码中看到这里是执行了new String()操作。所以
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
no.4
String s1 = new String("abc");
String si = s1.intern();
String s2 = "abc";
System.out.println(s1 == s2);// false
System.out.println(si == s2);// true
这里主要是对intern()方法的理解;intern()方法是一个native方法(是直接由c语言或者c++语言直接编写的方法)。intern()方法主要作用就是检查字符串常量池中是否有这个字符串,如果存在则返回这个字符串,如果不存在的话就是保存一份,然后再返回。
public native String intern();
内存分配图:
no.5
String s1 = new String("zh")+new String("y");
String si = s1.intern();
String s2 = "zhy";
System.out.println(s1 == s2);// true
System.out.println(si == s2);// true
这个结果是根据jdk1.7进行改造,之前的版本中执行intern()方法都是判断常量池中是否包含某个字符串的常量值,1.7之后就是判断将地址值copy一份到常量池中,所以造成了no.5中的结果。
对no4与no.5的结果进行判断要看执行intern的时候是将什么值放入到常量池中,然后从常量池中将什么值取了出来。
参考资料:
https://blog.csdn.net/Sqirt/article/details/72765071
https://blog.csdn.net/superlover_/article/details/93719290
张国荣《Monica》(我写这篇文章的时候听的歌 :))