String的==和equals()
String
String对象初始化
-
Method 1:
String 字符串名 = "字符串内容";
-
Method 2:
String 字符串名 = new String("字符串内容");
上面两种格式生成的字符串效果是相同的,但是存储机制是存在很大区别的!
Java为String类提供了一种称为缓存池机制的功能。使用Method 1的方式,直接赋值生成字符串,Java编译器总是先到缓冲池中去寻找是否存在相同内容的字符串。如果存在就可以直接使用,如果不存在则在缓冲池中创建一个新的字符串。使用Method 2的方式,用new关键字调用构造方法的方式,则每次调用都会生成一个新的String对象。
String关于“==”和equals()的比较
-
“==”是关系运算符,可以用于判断基本数据类型的变量值是否相等,或者判断引用类型变量的引用地址是否相同。
-
equals()方法,用于判断引用对象的引用地址所指向的存储内容是否相等。
纸上得来终觉浅,绝知此事要躬行,下面代码来证:
public class StringDemo { public static void main(String[] args) { String str1 = "Java String test"; String str2 = "Java String test"; String str3 = new String("Java String test"); String str4 = str3; System.out.println("str1="+str1+"、str2="+str2+"\n"+"str3="+str3+"、str4="+str4); if (str1 == str2) { System.out.println("str1 == str2: true"); }else { System.out.println("str1 == str2: false"); } if (str3 == str4) { System.out.println("str3 == str4: true"); }else { System.out.println("str3 == str4: false"); } if (str1 == str3) { System.out.println("str1 == str3: true"); }else { System.out.println("str1 == str3: false"); } } }
运行之后输出结果如下:
str1=Java String test、str2=Java String test str3=Java String test、str4=Java String test str1 == str2: true str3 == str4: true str1 == str3: false
结合下图对象在内存中的地址,来进行深入理解一下:
从上图中可知,String类型的内容是保存在堆内存中的,栈内存仅保存指向堆内存的地址,上面说到过String使用直接赋值生成对象,会用到缓冲池机制。在执行String str1 = “Java String test”时,在缓冲池中并没有“Java String test”字符串,所以生成一个“Java String test”字符串。执行到String str2 = “Java String test”时,缓冲池中已存在“Java String test”字符串,所以不需要生成一个新的“Java String test”字符串,而是直接使用该字符串。使用new关键字调用构造方法生成字符串时,不会用到缓冲池机制。每次调用一次就会生成一个新的字符串对象。
由于缓冲池机制,str1和str2使用相同的字符串对象,所以它们的内存地址是相等的,所以使用“==”关系运算符比较str1和str2结果值为true。同理,因为str1和str3指向不同的内存地址,所以str1==str3的结果值是false。从上图中可见,str3和str4指向同一内存地址,所以str3==str4的结果值为true。
上面通过代码来验证出了“==”是比较的对象的内存地址,下面看看equals(),上代码:
public class StringDemo {
public static void main(String[] args) {
String str1 = "Java String test";
String str2 = "Java String test";
String str3 = new String("Java String test");
String str4 = str3;
System.out.println("str1="+str1+"、str2="+str2+"\n"+"str3="+str3+"、str4="+str4);
if (str1.equals(str2)) {
System.out.println("str1.equals(str2): true");
}else {
System.out.println("str1.equals(str2): false");
}
if (str3.equals(str4)) {
System.out.println("str3.equals(str4): true");
}else {
System.out.println("str3.equals(str4): false");
}
if (str1.equals(str3)) {
System.out.println("str1.equals(str3): true");
}else {
System.out.println("str1.equals(str3): false");
}
}
}
运行结果如下:
str1=Java String test、str2=Java String test
str3=Java String test、str4=Java String test
str1.equals(str2): true
str3.equals(str4): true
str1.equals(str3): true
由于equals()方法是Object类中定义的一个方法,所有的类都继承自Object类,因此该方法可以在其他引用类型中使用。在这里String已经重写了Object类的equals()方法。从运行结果并结合上图可以看出equals()方法是比较的引用对象的引用地址所指向的存储内容是否相等。
总结
String初始化有两种方式,一般情况下是使用 String 字符串名 = “字符串内容” 的格式,因为此格式使用缓冲池机制执行效率高,节约内存。一个字符串就是一个String类的匿名对象,匿名对象是可以直接开辟堆内存并使用的对象。String 字符串 = new String(“字符串内容”) 格式分别需要开辟一个栈内存和一个堆内存。