接下来通过一个例子,详细了解String对象的两种不同创建方法。
Animal
package bean;
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
}
大家可以尝试着输出main
中的结果
import bean.Animal;
public class one {
public static void main(String[] args) {
String s1 = "huhai";
Animal a = new Animal(s1);
Animal b = new Animal(s1);
System.out.println(String.format("a == b : %s", a == b));
System.out.println(String.format("a.equals(b) : %s", a.equals(b)));
System.out.println(String.format("a.name == b.name : %s", a.name == b.name));
System.out.println(String.format("a.name.equals(b.name) : %s", a.name.equals(b.name)));
String s2 = new String("huhai");
String s3 = "huhai";
System.out.println(String.format("s1 == s2 : %s", s1 == s2));
System.out.println(String.format("s2 == s3 : %s", s2 == s3));
String t1 = "hello" + s1;
String t2 = "hellohuhai";
System.out.println(String.format("t1 == t2 : %s", t1 == t2));
System.out.println(String.format("t1.intern() == t2 : %s", t1.intern() == t2));
}
}
程序运行过程中内存变化
result
a == b : false
a.equals(b) : false
a.name == b.name : true
a.name.equals(b.name) : true
s1 == s2 : false
s2 == s3 : false
t1 == t2 : false
t1.intern() == t2 : true
分析
String s1 = "huhai"; // 先检查字符串常量池中有没有“huhai”,有则直接将s1指向它,没有则在常量池中创建一个,然后再指向它
Animal a = new Animal(s1);
Animal b = new Animal(s1);
System.out.println(String.format("a == b : %s", a == b)); // 引用对象的地址比较
System.out.println(String.format("a.equals(b) : %s", a.equals(b))); // 实际上还是判断地址
System.out.println(String.format("a.name == b.name : %s", a.name == b.name));
System.out.println(String.format("a.name.equals(b.name) : %s", a.name.equals(b.name)));
String s2 = new String("huhai");
String s3 = "huhai";
System.out.println(String.format("s1 == s2 : %s", s1 == s2));
System.out.println(String.format("s2 == s3 : %s", s2 == s3));
String t1 = "hello" + s1; // 底层调用了StringBuffer对象
String t2 = "hellohuhai";
System.out.println(String.format("t1 == t2 : %s", t1 == t2));
System.out.println(String.format("t1.intern() == t2 : %s", t1.intern() == t2)); // t1.intern()表示t1在常量池中的地址
总结
- 直接使用双引号声明出来的 String 对象会直接存储在常量池中。
- 如果不是用双引号声明的 String 对象,可以使用 String 提供的
intern()
方法。String.intern()
是一个 Native 方法,它的作用是:如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用; - “==”对于基本类型是值比较,对于引用类型是比较引用地址。
- “equals()” 一般是值比较