针对str1==str2问题
1.说明
1.1.str1==str2返回值为true或者false,判断依据为str1和str2是否为同一个引用。
1.2 str1.equals(str2)返回值为true和false,判断依据为字符串中每一个字符是否相等(区分大小写)和字符串长度是否相等
2.举例说明
2.1常量和引用
public class String01 {
public static void main(String[] args) {
String str1="hello";
String str2=new String("hello");
System.out.println(str1.equals(str2));
System.out.println(str1==str2);
}
}
//输出结果为
//true
//false
str1为""直接创建的,会保留在堆中的常量区,而str2是通过new String()创建的属于类的实例化,实际上str2保存的是实例化对象在堆空间的地址,str1.equals(str2)返回值为true只能说明str1和str2在字符大小写上和长度上都相等,而str1==str2返回值为false,说明他们实际的引用并不相同而出现返回值为false情况。
2.2常量与常量
public class String01 {
public static void main(String[] args) {
String str1="hello";
String str2="hello";
System.out.println(str1.equals(str2));
System.out.println(str1==str2);
}
}
//输出结果为
//true
//true
可以看出返回结果为true和true,这里只解释下第二个返回为true的原因。因为str1和str2都是从在常量区创建的,常量区的值在编译成为.class字节码的文件的时候就已经确定,str1和str2的值均为同一个常量的引用,所以返回为true
2.3引用与引用
public class String01 {
public static void main(String[] args) {
String str1=new String("hello");
String str2=new String("hello");
System.out.println(str1.equals(str2));
System.out.println(str1==str2);
}
}
//输出结果为
//true
//false
可以看出返回结果仍为true和false,这里只解释下false的原因。这里str1和str2虽然创建的字符串相同,但是由于都是通过实例化(new)创建的,与常量不同,需要在运行时创建在每一个实例化的时候都会分配不同的地址,所以str1和str2的引用(保存的地址)并不相同,所以返回为false。
2.4String.intern()方法
存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;
public class String01 {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = new String("hello");
str1.intern();
str2.intern();
System.out.println(str1.equals(str2));
System.out.println(str1 == str2)//比较intern会不会改变str原有的引用
System.out.println(str1 == str2.intern());
System.out.println(str1.intern() == str2.intern());//验证str.intern()方法的有效性
}
}
//输出结果为
//true
//false
//false
//true
第二个为false说明str.inter并不会覆盖原有的引用,只能通过返回值重新覆盖来改变
注:扩展内容
探秘Java中的String、StringBuilder以及StringBuffer
请查看链接