[英]Override the equals method
我目前正在為考試做准備。 在過去的論文中,有一個問題,
重寫以下類中的equals方法。 該方法應檢查整個狀態的內容是否相等。
class Employee
{
String firstName;
int age;
}
[2分]
我做了一些擺弄正確答案的擺弄,到目前為止已經提出了這個建議。 有沒有更簡單的方法來回答這個問題,對嗎? 非常感謝您的幫助。
public class Employee
{
int age;
public boolean equals(Object obj)
{
if(this == obj)
{
return true; //Reference equality.
}
if(!(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return firstName == other.firstName;
return age == other.age;
}
}
要點:
obj
是否為null
。 String
內容,請使用equals()
,即firstName.equals(other.firstName)
。 首先檢查firstName
是否為null
。 這是一個改進的實現:
public boolean equals(Object obj)
{
if(obj == null)
{
return false;
}
if(this == obj)
{
return true; //Reference equality.
}
if(this.getClass() != obj.getClass())
{
return false;
}
Employee other = (Employee) obj;
if(firstName == null)
{
if(other.firstName != null)
{
return false;
}
}
else if(!firstName.equals(other.firstName))
{
return false;
}
return age == other.age;
}
編輯 :更新了類型比較,以根據@Mark Peters的答案使equals()
對稱。
采用
return (((this.firstName == null || other.firstName == null)
&& this.firstName == other.firstName)
||
this.firstName.equals(other.firstName))
&& age == other.age;
這也處理null
情況。
字符串firstName應該與.equals()進行比較,而不是==。 對於原始int age字段,==比較可以。
如果兩個名字相同但年齡不相等怎么辦? 這不應該失敗嗎?
類似於return (firstName.equals(obj.firstName)) && (age == obj.age);
當然,如果this.firstName為null,則不會考慮這種情況,這將導致拋出NullPointerException
。
如果雇員的名字都為空,是否認為雇員平等? 如果一個為空而另一個不為空怎么辦? 假設兩者都必須為null,或者兩者都必須為String.equals(),則可以使用:
return ((null == firstName && null == obj.firstName)
|| (null != firstName && firstName.equals(obj.firstName)))
&& (age == obj.age);
而不是您的2個return語句。 其余的看起來還可以。
需要注意的一件事,我不會想象您會在考試中陷入困境……
當類不是最終的時,執行instanceof
通常是不佳的做法。 這是因為equals()
必須對稱。 接受子類(它們也可能使用其自己的新方面實現equals)可能導致其不對稱。
示例(我認為該示例與Effective Java 2ed中使用的示例相同):
class Point {
protected int x, y;
//equals method uses instanceof Point and checks x and y values are the same
}
class ColorPoint extends Point {
protected Color color;
//equals method checks that it's a ColorPoint, that super.equals is true,
//then checks the Color
}
new Point(1, 2).equals(new ColorPoint(1, 2, Color.red)); //true
new ColorPoint(1, 2, Color.red).equals(new Point(1, 2)); //false
這是非常微妙的一點,即使這里的大多數答題者也沒有考慮到。 但這是大多數equals
生成器(例如您最喜歡的IDE中的生成器)傾向於進行精確的類比較的原因:
if ( this.getClass() != other.getClass() ) {
return false;
}
當equals方法使用instanceof時,通常最好記錄子類必須遵循完全相同的規范。
您的最后一行(年齡比較)無法訪問; 您不應該使用==
比較字符串; 並且您需要考慮空值。
由於一般的運動似乎是為您全力以赴,因此這里是Eclipse的實現:
public class Employee {
private final String firstName;
private final int age;
public Employee(final String firstName, final int age) {
super();
this.firstName = firstName;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (age != other.age) {
return false;
}
if (firstName == null) {
if (other.firstName != null) {
return false;
}
} else if (!firstName.equals(other.firstName)) {
return false;
}
return true;
}
}
並進行一系列測試:
import org.junit.Test;
public class EmployeeTest {
@Test
public void testEmployeeEquals() {
final Employee nullNameEmp = new Employee(null, -1);
final Employee empA1 = new Employee("a", 1);
final Employee empA1Clone = new Employee("a", 1);
final Employee empA2 = new Employee("a", 2);
final Employee empB1 = new Employee("b", 1);
final Employee empB2 = new Employee("b", 2);
final Employee subEmp = new Employee("a", 1) {
};
assert !nullNameEmp.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !nullNameEmp.equals(empA2);
assert !nullNameEmp.equals(empB1);
assert !nullNameEmp.equals(empB2);
assert !nullNameEmp.equals(subEmp);
assert !nullNameEmp.equals(null);
assert !empA1.equals(nullNameEmp);
assert empA1.equals(empA1Clone);
assert !empA1.equals(empA2);
assert !empA1.equals(empB1);
assert !empA1.equals(empB2);
assert !empA1.equals(subEmp);
assert !empA1.equals(null);
assert !empA2.equals(nullNameEmp);
assert !empA2.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !empA2.equals(empB1);
assert !empA2.equals(empB2);
assert !empA2.equals(subEmp);
assert !empA2.equals(null);
assert !empB1.equals(nullNameEmp);
assert !empB1.equals(empA1);
assert !empB1.equals(empA1Clone);
assert !empB1.equals(empA2);
assert !empB1.equals(empB2);
assert !empB1.equals(subEmp);
assert !empB1.equals(null);
assert !empB2.equals(nullNameEmp);
assert !empB2.equals(empA1);
assert !empB2.equals(empA1Clone);
assert !empB2.equals(empA2);
assert !empB2.equals(empB1);
assert !empB2.equals(subEmp);
assert !empB2.equals(null);
assert !subEmp.equals(nullNameEmp);
assert !subEmp.equals(empA1);
assert !subEmp.equals(empA1Clone);
assert !subEmp.equals(empA2);
assert !subEmp.equals(empB1);
assert !subEmp.equals(empB2);
assert !subEmp.equals(null);
assert nullNameEmp.equals(nullNameEmp);
assert empA1.equals(empA1);
assert empA1Clone.equals(empA1Clone);
assert empA2.equals(empA2);
assert empB1.equals(empB1);
assert empB2.equals(empB2);
assert subEmp.equals(subEmp);
}
}
public boolean equals(Object o){
if(this==o){ //same instance, no need to check more
return true;
}
if(o instanceof Employee){ //when null this will yield false
Employee other = (Employee) o;
return (this.name == other.name || (this.name != null && this.name.equals(other.name)) && this.age == other.age;
}
return false;
}
將所有已經提到的部分歸納為一個答案:
public boolean equals(Object obj) {
if(this == obj) {
return true; //Reference equality.
}
if(obj == null || !(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return (firstName.equals(other.firstName) && age == other.age);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.