简介
在这个实验中,你将学习如何在 Java 中检查两个对象是否相等。我们将探讨使用 ==
运算符和 equals()
方法进行对象比较的根本区别。
你将首先使用内置的 equals()
方法来比较对象,并了解它在不同数据类型下的行为。然后,你将学习如何在自己的自定义类中重写 equals()
方法,以定义你的对象的逻辑相等性。最后,你将处理在执行相等性检查时处理空对象的重要问题,以防止潜在的 NullPointerException
错误。
在这个实验中,你将学习如何在 Java 中检查两个对象是否相等。我们将探讨使用 ==
运算符和 equals()
方法进行对象比较的根本区别。
你将首先使用内置的 equals()
方法来比较对象,并了解它在不同数据类型下的行为。然后,你将学习如何在自己的自定义类中重写 equals()
方法,以定义你的对象的逻辑相等性。最后,你将处理在执行相等性检查时处理空对象的重要问题,以防止潜在的 NullPointerException
错误。
equals()
方法进行相等性比较在这一步中,我们将探讨如何在 Java 中使用 equals()
方法来比较对象。==
运算符用于检查两个对象引用是否指向内存中的同一个对象,而 equals()
方法则用于检查两个对象在逻辑上是否相等,即它们是否表示相同的值或状态。
让我们通过创建一个简单的 Java 文件来演示这个概念。
打开 WebIDE,确保你位于 ~/project
目录下。你可以通过查看终端提示符或输入 pwd
并按回车键来确认。
在 ~/project
目录下创建一个名为 EqualityDemo.java
的新文件。你可以通过在左侧的文件资源管理器中右键单击,选择“新建文件”,然后输入 EqualityDemo.java
来完成。
在编辑器中打开 EqualityDemo.java
文件,并粘贴以下代码:
public class EqualityDemo {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = str1;
System.out.println("Comparing String objects:");
System.out.println("str1 == str2: " + (str1 == str2));
System.out.println("str1.equals(str2): " + str1.equals(str2));
System.out.println("str1 == str3: " + (str1 == str3));
System.out.println("str1.equals(str3): " + str1.equals(str3));
System.out.println("\nComparing primitive types (int):");
int num1 = 10;
int num2 = 10;
System.out.println("num1 == num2: " + (num1 == num2));
}
}
在这段代码中:
String
对象 str1
和 str2
,它们具有相同的内容("hello"),但使用 new String()
创建,这会在内存中创建不同的对象。String
引用 str3
,并让它指向与 str1
相同的对象。==
和 equals()
来比较 str1
和 str2
,以及 str1
和 str3
。==
对基本数据类型 int
进行比较。请记住,equals()
用于对象,而不是基本数据类型。保存 EqualityDemo.java
文件(Ctrl+S 或 Cmd+S)。
打开 WebIDE 底部的终端。
输入以下命令并按回车键来编译 Java 程序:
javac EqualityDemo.java
如果没有错误,你应该看不到任何输出。
输入以下命令并按回车键来运行编译后的程序:
java EqualityDemo
你应该会看到类似于以下的输出:
Comparing String objects:
str1 == str2: false
str1.equals(str2): true
str1 == str3: true
str1.equals(str3): true
Comparing primitive types (int):
num1 == num2: true
注意,str1 == str2
的结果为 false
,因为它们是内存中的不同对象,尽管它们的内容相同。然而,str1.equals(str2)
的结果为 true
,因为 String
类的 equals()
方法被重写以比较字符串的实际内容。str1 == str3
的结果为 true
,因为 str3
指向与 str1
完全相同的对象。
这展示了在 Java 中比较对象时 ==
(引用相等性)和 equals()
(逻辑相等性)之间的关键区别。对于基本数据类型,==
用于值的比较。
equals()
方法在上一步中,我们了解了 equals()
方法如何用于 String
对象。String
类已经重写了默认的 equals()
方法(继承自 Object
类),以便根据内容进行有意义的比较。
然而,当你创建自己的自定义类时,从 Object
类继承的默认 equals()
方法只是使用 ==
运算符,这意味着它只检查引用是否相等。要根据自定义类对象的属性(逻辑相等性)来比较这些对象,你需要自己重写 equals()
方法。
在这一步中,我们将创建一个简单的 Person
类并重写其 equals()
方法。
确保你在 WebIDE 的 ~/project
目录中。
在 ~/project
目录中创建一个名为 Person.java
的新文件。
打开 Person.java
并粘贴以下 Person
类的代码:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// Default equals() method (inherited from Object) would only check reference equality
// We need to override it to check for logical equality based on name and age
@Override
public boolean equals(Object obj) {
// Step 1: Check if the objects are the same instance
if (this == obj) {
return true;
}
// Step 2: Check if the object is null or of a different class
if (obj == null || getClass() != obj.getClass()) {
return false;
}
// Step 3: Cast the object to the correct type
Person person = (Person) obj;
// Step 4: Compare the relevant attributes
return age == person.age &&
name.equals(person.name); // Use equals() for String comparison
}
}
在这个 Person
类中:
name
(字符串类型)和 age
(整数类型)。equals()
方法。让我们看看重写的 equals()
方法中的步骤:
if (this == obj)
:这是一种优化。如果两个引用指向同一个对象,它们肯定相等。if (obj == null || getClass() != obj.getClass())
:这会检查要比较的对象是否为 null 或者是否不是 Person
类的实例。如果其中任何一个条件为真,它们就不可能相等。Person person = (Person) obj;
:我们将通用的 Object
类型转换为 Person
对象,以便可以访问其 name
和 age
属性。return age == person.age && name.equals(person.name);
:这是逻辑比较的核心。我们检查 age
是否相同(对于基本整数类型使用 ==
)以及 name
是否相同(对于 String
对象使用 equals()
)。保存 Person.java
文件。
现在,让我们创建另一个文件 PersonEqualityDemo.java
来测试我们重写的 equals()
方法。在 ~/project
目录中创建这个文件。
打开 PersonEqualityDemo.java
并粘贴以下代码:
public class PersonEqualityDemo {
public static void main(String[] args) {
Person person1 = new Person("Alice", 30);
Person person2 = new Person("Alice", 30);
Person person3 = new Person("Bob", 25);
Person person4 = person1;
System.out.println("Comparing Person objects:");
System.out.println("person1 == person2: " + (person1 == person2));
System.out.println("person1.equals(person2): " + person1.equals(person2));
System.out.println("person1 == person3: " + (person1 == person3));
System.out.println("person1.equals(person3): " + person1.equals(person3));
System.out.println("person1 == person4: " + (person1 == person4));
System.out.println("person1.equals(person4): " + person1.equals(person4));
}
}
在这个演示类中,我们创建了几个 Person
对象,并使用 ==
和我们重写的 equals()
方法对它们进行比较。
保存 PersonEqualityDemo.java
文件。
打开终端。确保你在 ~/project
目录中。
编译这两个 Java 文件。你可以一次编译多个文件:
javac Person.java PersonEqualityDemo.java
这应该会创建 Person.class
和 PersonEqualityDemo.class
文件。
运行演示程序:
java PersonEqualityDemo
你应该会看到类似于以下的输出:
Comparing Person objects:
person1 == person2: false
person1.equals(person2): true
person1 == person3: false
person1.equals(person3): false
person1 == person4: true
person1.equals(person4): true
正如预期的那样,person1 == person2
为 false
,因为它们是不同的对象,但 person1.equals(person2)
为 true
,因为根据我们重写的方法,它们的 name
和 age
是相同的。person1
和 person3
在两种比较方式下都不相等。person1
和 person4
在两种比较方式下都相等,因为它们引用同一个对象。
通过重写 equals()
方法,你可以根据自定义类对象的逻辑状态而不仅仅是它们的内存位置来定义“相等”的含义。
在上一步中,我们成功地在 Person
类中重写了 equals()
方法,以便根据对象的属性进行比较。编写健壮的 equals()
方法的一个关键方面是处理潜在的 null
值。如果你尝试在 null
对象上调用方法,将会导致 NullPointerException
,这是 Java 中常见的错误。
我们在 Person.java
中重写的 equals()
方法已经包含了对 null
的检查:if (obj == null || getClass() != obj.getClass())
。这是处理被比较对象为 null
情况的标准方法。
在这一步中,我们将演示将对象与 null
进行比较时会发生什么,并确认我们的 equals()
方法能够正确处理这种情况。
确保你在 WebIDE 的 ~/project
目录中。
打开你在上一步中创建的 PersonEqualityDemo.java
文件。
在 main
方法中,在现有的比较语句之后添加以下代码行:
System.out.println("\nComparing with null:");
System.out.println("person1.equals(null): " + person1.equals(null));
这段代码只是添加了 person1
与 null
的比较。
保存 PersonEqualityDemo.java
文件。
打开终端。确保你在 ~/project
目录中。
编译修改后的 PersonEqualityDemo.java
文件:
javac PersonEqualityDemo.java
请记住,你只需要重新编译你修改过的文件。由于在这一步中 Person.java
没有被修改,我们只需要编译 PersonEqualityDemo.java
。
运行编译后的程序:
java PersonEqualityDemo
你现在应该会看到之前的输出,后面跟着与 null
的新比较结果:
Comparing Person objects:
person1 == person2: false
person1.equals(person2): true
person1 == person3: false
person1.equals(person3): false
person1 == person4: true
person1.equals(person4): true
Comparing with null:
person1.equals(null): false
输出 person1.equals(null): false
确认了我们重写的 equals()
方法能够正确处理与 null
的比较,并返回 false
,而不会抛出 NullPointerException
。这是因为在我们 Person
类的 equals()
方法中,if (obj == null || getClass() != obj.getClass())
这一行在尝试访问 obj
的任何属性之前会先检查是否为 null
。
在 Java 中,处理 null
是编写健壮代码的关键部分,尤其是在处理对象比较时。始终在重写的 equals()
方法开头包含 null
检查。
在这个实验中,我们学习了如何在 Java 中检查两个对象是否相等。我们首先了解了 ==
运算符和 equals()
方法之间的区别,==
运算符用于检查引用是否相等,而 equals()
方法用于检查逻辑是否相等。我们通过 String
对象和基本数据类型演示了这一点,观察到 ==
运算符和 equals()
方法在处理对象时的不同表现。
然后,我们探讨了如何在自定义类中重写 equals()
方法,以定义我们自己的对象相等性标准。这对于确保我们的自定义对象基于其内容或状态进行比较,而不仅仅是基于其内存位置进行比较至关重要。最后,我们了解了在 equals()
方法中处理空对象的重要性,以防止出现 NullPointerException
并确保进行健壮的相等性检查。