介绍
在这个实验中,你将学习如何在 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(整数类型)。 - 我们有一个构造函数来初始化这些属性。
- 我们有获取属性的 getter 方法。
- 我们重写了
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 并确保进行健壮的相等性检查。



