2015-11-12 142 views
3

我有與多個實例變量(一個字符串的倍數整數) 我要創建將檢查執行方法的對象之間的平等的方法和創建的對象的衆多另一個對象。我的意思是我想通過調用一個方法來查看兩個對象的所有實例變量是否相同。我正在考慮類似於equals方法(string1.equals(string2)),但是我可以對具有多個不是所有字符串的多個實例變量的對象執行相同操作嗎?比較兩個類對象與方法

例如:

//object1 
    String name1= keyb.nextLine(); 
    int age1= keyb.nextInt(); 
    int monthborn1; 

    //object2 
    String name2=keyb.nextLine(); 
    int age2 = keyb.nextInt(); 
    int monthborn2; 

我需要做的是比較兩個對象,並認爲它們是否相等或不的方法。

非常感謝。

回答

4

是的,您可以爲您的課程創建equals方法。例如:

public final class Person { 
    private final String name; 
    private final int age; 
    private final int birthMonth; 

    public Person(String name, int age, int birthMonth) { 
     this.name = Objects.requireNonNull(name); 
     this.age = age; 
     this.birthMonth = birthMonth; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (o instanceof Person) { 
      Person rhs = (Person) o; 
      return name.equals(rhs.name) 
        && age == rhs.age 
        && birthMonth == rhs.birthMonth; 
     } 
     return false; 
    } 

    // Any time you override `equals`, you must make a matching `hashCode`. 
    // This implementation of `hashCode` is low-quality, but demonstrates 
    // the idea. 
    @Override 
    public int hashCode() { 
     return name.hashCode()^age^birthMonth; 
    } 
} 
+0

我可能會讓'Person'' final'或者'equals'和'hashCode'' final'使得不可能子類Person並違反對稱性。 –

+0

@Chris Jester-Young♦謝謝你的幫助!你介意解釋爲什麼我們需要重寫後的哈希碼?我仍然是編程新手。 –

+1

@ R.DM當使用對象作爲散列鍵時使用散列碼。散列碼的「契約」是相同的對象(所有對象'a'和'b',其中'a.equals(b)'返回true)必須具有相同的散列碼。如果你不重寫'hashCode',默認的哈希碼就是「身份哈希碼」,即使它們使用equals來比較相等的值,每個對象也是不同的。這就是爲什麼'hashCode'和'equals'完全相同的字段比較重要。 –

2

在Java中,通常必須先手動檢查每一個領域是這樣的:

class MyObject { 
    String name; 
    int age, monthborn; 

    public boolean isEqual(MyObject other) { 
     return Objects.equals(name, other.name) && 
       age == other.age && monthborn == other.monthborn; 
    } 
} 

Objects.equals在這裏使用它是name.equals(other.name)空安全等同。當您添加新字段時,您還必須在方法中添加新的檢查。另一種方法是利用反射,但它看起來很醜並且有明顯的性能缺陷。這裏有一個例子草案如何做到這一點(不考慮可能的繼承):

import java.lang.reflect.Field; 
import java.util.Objects; 

public class ObjectUtil { 
    public static <T> boolean allFieldsEqual(T o1, T o2) throws IllegalAccessException { 
     if(o1 == o2) return true; 
     if(o1.getClass() != o2.getClass()) return false; 
     for(Field field : o1.getClass().getDeclaredFields()) { 
      field.setAccessible(true); 
      if(!Objects.equals(field.get(o1), field.get(o2))) { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

class MyObject { 
    String name; 
    int age, monthborn; 

    public boolean isEqual(MyObject other) { 
     try { 
      return ObjectUtil.allFieldsEqual(this, other); 
     } catch (IllegalAccessException e) { 
      return false; 
     } 
    } 
} 

這樣在添加新的領域isEqual方法會考慮到這一點爲好。但我不會推薦這樣的解決方案。

+0

我在我的回答中採取了相反的方式:我的構造函數有一個明確的'Objects.requireNonNull'調用。這樣,'equals'和'hashCode'不需要擔心空值。 –

+1

@ ChrisJester-Young,這取決於用戶的需求,儘管可能用於'name'字段'requireNonNull' *通常*更適合業務邏輯。 –

0

請參閱本answer。此外,由於您正在重寫equals方法,因此您應該重寫散列碼方法(也包含在鏈接的文章中)。

0

一旦你比較兩個對象,你必須考慮所有類的成員。

我們假設我們有一個名爲,並與兩個成員變量年齡和類。

B類:

public class B { 
    String name; 
    int age; 

    public B(String name, int age) { 
     this.age = age; 
     this.name = name; 
    } 
} 

然後讓使用被從Object類繼承我們的B類equalshashcode方法比較同一類的兩個不同的對象。

A級比較:

public class A { 
    public static void main(String args[]){ 
     B b1 = new B("a", 22); 
     B b2 = new B("a",22); 
     System.out.println(b1.equals(b2)); 
     System.out.println(b1.hashCode()); 
     System.out.println(b2.hashCode()); 
    } 
} 

只要我們編譯和運行A級,我們將得到以下外看跌期權。

false 
705927765//returns int value 
366712642//returns int value 

但這裏的A類已通過相同的參數給的兩個對象。這意味着我們得到了我們沒想到的,因爲equalshashcode方法在對象類沒有做我們需要的。 因此,在這種情況下,我們必須在我們的B類中重寫這些方法以使其成功。

B類覆蓋完成後:

public class B { 
    String name; 
    int age; 

    public B(String name, int age) { 
     this.age = age; 
     this.name = name; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     boolean flag = false; 
     if (obj instanceof B) { 
      B b = (B) obj; 
      if (this.age == b.age) { 
       if (this.name.charAt(0)==b.name.charAt(0))) { 
        flag = true; 
       } else { 
        flag = false; 
       } 
      } else { 
       flag = false; 
      } 
     } else { 
      flag = false; 
     } 
     return flag; 
    } 
    @Override 
    public int hashCode() { 
     return this.age+this.name.charAt(0); 

    } 
} 

如果我們運行A級再次,我們可以得到follwing結果:

true 
119 
119 

這意味着我們的工作就完成了。

+0

你爲什麼只比較名字的第一個字母?而且,所有嵌套的'if's可以通過更廣泛地使用'&&'來完成。 –