Java笔记 == 和 equals()

133 阅读4分钟

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

在这个示例中,我们比较了两个整数变量 ab 的值,使用 == 运算符比较它们的值,因此结果为 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 对象 person1person2,尽管它们具有相同的属性值(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 对象 obj1obj2,这将比较它们的引用地址,因此结果为 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 对象 str1str2String 类重写了 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。