1. == 和 equals():
(1)“==” 用于比较基本数据类型时比较的是值,用于比较引用类型时比较的是引用指向的地址。
(2) Object 中的equals() 与 “==” 的作用相同,但String类重写了equals()方法,比较的是对象中的内容。
1.1. 比较基本数据类型:
int a = 5;
int b = 5;
boolean result = (a == b);
System.out.println(result); // 输出 true
在这个示例中,我们比较了两个整数变量 a 和 b 的值,使用 == 运算符比较它们的值,因此结果为 true,因为它们的值相等。
1.2. 比较引用类型:
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
Person person1 = new Person("Alice");
Person person2 = new Person("Alice");
boolean result = (person1 == person2);
System.out.println(result); // 输出 false
在这个示例中,我们创建了两个不同的 Person 对象 person1 和 person2,尽管它们具有相同的属性值(name),但它们是不同的对象,因此使用 == 运算符比较它们将返回 false,因为它们引用不同的内存地址。
接下来,让我们讨论 Object 类中的 equals() 方法和 String 类中的 equals() 方法。
1.3. Object 类中的 equals() 方法:
Object obj1 = new Object();
Object obj2 = new Object();
boolean result = obj1.equals(obj2);
System.out.println(result); // 输出 false
在这个示例中,我们使用 equals() 方法来比较两个 Object 对象 obj1 和 obj2,这将比较它们的引用地址,因此结果为 false,因为它们引用不同的内存地址。
1.4. String 类中的 equals() 方法:
String str1 = new String("Hello");
String str2 = new String("Hello");
boolean result = str1.equals(str2);
System.out.println(result); // 输出 true
在这个示例中,我们使用 equals() 方法来比较两个 String 对象 str1 和 str2,String 类重写了 equals() 方法,以比较对象中的内容而不是引用地址。因此,结果为 true,因为它们包含相同的字符串内容。
总之,== 运算符用于比较基本数据类型时比较的是值,用于比较引用类型时比较的是引用指向的地址。而 equals() 方法可以用于比较引用类型的内容,但需要注意不同的类可能会对 equals() 方法进行不同的实现。在 String 类中,equals() 方法已被重写,以比较字符串的内容。
2. String对象的两种创建方式:
- 第一种方式:
String str1 = "aaa";
-
- 在常量池中获取对象
- "aaa" 属于字符串字面量,编译时期会在常量池中创建一个字符串对象,如果常量池中已存在该字符串对象,则直接引用。
- 第二种方式:
String str2 = new String("aaa");
-
- 会创建两个字符串对象,一个在堆中,一个在常量池中(前提是常量池中还没有 "aaa" 对象)。
System.out.println(str1==str2); //false
3. String类型的常量池特点:
- 直接使用双引号声明的String对象会直接存储在常量池中。
- 如果不是用双引号声明的String对象,可以使用
String提供的intern()方法。String.intern()是一个 Native 方法,它的作用是:
-
- 如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用。
- 如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用。
示例:
String s1 = new String("AAA");
String s2 = s1.intern();
String s3 = "AAA";
System.out.println(s2); // AAA
System.out.println(s1 == s2); // false,因为一个是堆内存中的String对象,一个是常量池中的String对象
System.out.println(s1 == s3); // false,== 运算符用于比较两个对象的引用地址。用指向不同的对象,地址也不同
System.out.println(s2 == s3); // true,s1, s2 指向常量池中的 "AAA"
4. 字符串拼接:
String a = "a";
String b = "b";
String str1 = "a" + "b"; // 常量池中的对象
String str2 = a + b; // 在堆上创建的新的对象 引用的是堆内存中的新字符串对象。
String str3 = "ab"; // 常量池中的对象
System.out.println(str2 == str1); // false
System.out.println(str2 == str3); // false
System.out.println(str1 == str3); // true
在Java中,字符串字面量(例如:"ab")在首次出现时会被存储在常量池中。因此,当您创建了 str1 时,它引用了常量池中的字符串对象 "ab"。然后,当您创建 str3 时,它会直接引用已经存在于常量池中的 "ab",因为相同的字符串字面量在常量池中只会存储一次。
因此,str1 和 str3 都引用了常量池中的相同的字符串对象,它们的引用地址是相同的,所以 str1 == str3 返回 true。