So sánh hai đối tượng với toán tử .equals () và ==


84

Tôi đã xây dựng một lớp với một Stringtrường. Sau đó, tôi tạo hai đối tượng và tôi cũng phải so sánh chúng bằng ==toán tử .equals(). Đây là những gì tôi đã làm:

public class MyClass {

    String a;

    public MyClass(String ab) {
        a = ab;
    }

    public boolean equals(Object object2) {
        if(a == object2) { 
            return true;
        }
        else return false;
    }

    public boolean equals2(Object object2) {
        if(a.equals(object2)) {
            return true;
        }
        else return false;
    }



    public static void main(String[] args) {

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        object1.equals(object2);
        System.out.println(object1.equals(object2));

        object1.equals2(object2);
        System.out.println(object1.equals2(object2));
    }


}

Sau khi biên dịch, kết quả là nó sai hai lần. Tại sao nó sai nếu hai đối tượng có cùng trường - "thử nghiệm"?


7
Btw, nhìn vào equalsequals2: bất cứ khi nào bạn có một cái gì đó ở dạng if(a) { return true; } else { return false; }có thể bạn chỉ cần viết return a.
yshavit

@yshavit Ý bạn là, với sự thay đổi từ boolean thành String?
Fastkowy 14/11/12

4
không, mã của bạn đang hỏi liệu boolean có phải là true hay không và trả về truenếu nó đúng và falsengược lại. Vì vậy, chẳng hạn, if(a.equals(object2)) { return true; } else return falsechỉ có thể là return a.equals(object2).
yshavit

Câu trả lời:


142

==so sánh các tham chiếu đối tượng, nó kiểm tra xem hai toán hạng có trỏ đến cùng một đối tượng hay không (không phải đối tượng tương đương , cùng một đối tượng).

Nếu bạn muốn so sánh các chuỗi (để xem chúng có chứa các ký tự giống nhau hay không), bạn cần so sánh các chuỗi bằng cách sử dụng equals.

Trong trường hợp của bạn, nếu hai trường hợp MyClassthực sự được coi là bằng nhau nếu các chuỗi khớp nhau, thì:

public boolean equals(Object object2) {
    return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}

... nhưng thông thường nếu bạn đang xác định một lớp, có nhiều thứ tương đương hơn là tính tương đương của một trường đơn lẻ ( atrong trường hợp này).


Lưu ý phụ: Nếu bạn ghi đè equals, bạn hầu như luôn luôn cần ghi đè hashCode. Như nó nói trong equalsJavaDoc :

Lưu ý rằng thường cần ghi đè hashCodephương thức bất cứ khi nào phương thức này bị ghi đè, để duy trì hợp đồng chung cho hashCodephương thức, trong đó quy định rằng các đối tượng bằng nhau phải có mã băm bằng nhau.


@TJ In == so sánh các tham chiếu đối tượng, để giải thích, Có nghĩa là == so sánh mã băm của hai đối tượng?
Narendra Jaggi

@NarendraJaggi - Không, có nghĩa là JVM kiểm tra xem hai toán hạng có tham chiếu đến cùng một đối tượng hay không. Nó thực hiện điều đó như thế nào là tùy thuộc vào JVM, nhưng không có lý do gì để nghĩ rằng nó sẽ sử dụng mã băm để làm điều đó.
TJ Crowder

19

Bạn nên ghi đè bằng

 public boolean equals (Object obj) {
     if (this==obj) return true;
     if (this == null) return false;
     if (this.getClass() != obj.getClass()) return false;
     // Class name is Employ & have lastname
     Employe emp = (Employee) obj ;
     return this.lastname.equals(emp.getlastname());
 }

2
Đây được cho là câu trả lời tốt nhất, tuy nhiên bạn có thể muốn sử dụng this.equals (obj) thay vì (null == này) với nhiều loại phi nguyên thủy
goonerify

10
Tôi cho rằng if (this == null)trường hợp này dù sao cũng không cần thiết; việc gọi nullObject.equals(whatever)sẽ ném ra một ngoại lệ con trỏ null, vì vậy chúng ta có thể an toàn cho rằng thisnó không phải là null trong bất kỳ phương thức Java nào mà chúng ta có thể viết.
Maura

1
điều này sẽ không thành công khi thislastnamenull và không thỏa mãn các điều kiện trước đó.
Ahmed Raaj

6

Có vẻ như equals2chỉ là gọi điện equals, vì vậy nó sẽ cho kết quả tương tự.


5

Hàm ghi đè bằng () là sai. Đối tượng "a" là một thể hiện của lớp String và "object2" là một thể hiện của lớp MyClass . Chúng là các lớp khác nhau, vì vậy câu trả lời là "sai".


5

Cách tốt nhất để so sánh 2 đối tượng là chuyển đổi chúng thành chuỗi json và so sánh các chuỗi, giải pháp dễ dàng nhất khi xử lý các đối tượng, trường và / hoặc đối tượng lồng nhau phức tạp có chứa mảng.

mẫu vật:

import com.google.gson.Gson;


Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b); 

if(objectString1.equals(objectString2)){
    //do this
}

9
Tôi muốn gọi điều này là: quá mức cần thiết.
Rolf ツ

@Rolf ツ Theo bạn tại sao điều này là quá mức cần thiết? Tôi đã tìm kiếm giải pháp cho vấn đề này và đây là giải pháp dễ nhất mà tôi tìm thấy cho đến nay. Mọi đề xuất tốt hơn đều được hoan nghênh.
m5seppal

3
Vì với Java, bạn có thể so sánh các đối tượng mà không cần tạo Gsonđối tượng trước rồi mới gọi toJson. Việc tạo Gsonđối tượng và gọi logic cần thiết để chuyển đổi đối tượng thực sự thành một flat String( toJson) là không cần thiết. Bạn có thể so sánh các đối tượng mà không cần chuyển đổi đối tượng thành chuỗi Json trước (cũng nhanh hơn).
Rolf ツ

3

equals2()Phương thức của bạn sẽ luôn trả về giống như equals()!!

Mã của bạn với nhận xét của tôi:

public boolean equals2(Object object2) {  // equals2 method
    if(a.equals(object2)) { // if equals() method returns true
        return true; // return true
    }
    else return false; // if equals() method returns false, also return false
}

5
Justreturn a.equals(object2);
mojuba

2

Các câu lệnh a == object2a.equals(object2)cả hai sẽ luôn trả về falseamột stringthời gian object2là một ví dụ củaMyClass


2

Việc triển khai của bạn phải như sau:

public boolean equals2(Object object2) {
    if(a.equals(object2.a)) {
        return true;
    }
    else return false;
}

Với việc triển khai này, cả hai phương pháp của bạn sẽ hoạt động.


2

Nếu bạn không cần tùy chỉnh hàm toString () mặc định, một cách khác là ghi đè phương thức toString (), phương thức này trả về tất cả các thuộc tính cần so sánh. sau đó so sánh đầu ra toString () của hai đối tượng. Tôi đã tạo phương thức toString () bằng cách sử dụng IntelliJ IDEA IDE, bao gồm tên lớp trong chuỗi.

public class Greeting {
private String greeting;

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    return this.toString().equals(obj.toString());
}

@Override
public String toString() {
    return "Greeting{" +
            "greeting='" + greeting + '\'' +
            '}';
}
}

2

Toán tử "==" chỉ trả về true nếu hai tham chiếu trỏ đến cùng một đối tượng trong bộ nhớ. Mặt khác, phương thức equals () trả về true dựa trên nội dung của đối tượng.

Thí dụ:

String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");

//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println("Comparing two strings with == operator: " + result);

//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println("Comparing two Strings with same content using equals method: " + result);

homeLoan = personalLoan;
//since both homeLoan and personalLoan reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);

Kết quả: So sánh hai chuỗi với toán tử ==: false So sánh hai chuỗi có cùng nội dung sử dụng phương thức equals: true So sánh hai tham chiếu trỏ đến cùng một chuỗi với toán tử ==: true

Bạn cũng có thể biết thêm chi tiết từ liên kết: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2

Lớp của bạn có thể triển khai giao diện So sánh để đạt được chức năng tương tự. Lớp của bạn nên triển khai phương thức CompareTo () được khai báo trong giao diện.

public class MyClass implements Comparable<MyClass>{

    String a;

    public MyClass(String ab){
        a = ab;
    }

    // returns an int not a boolean
    public int compareTo(MyClass someMyClass){ 

        /* The String class implements a compareTo method, returning a 0 
           if the two strings are identical, instead of a boolean.
           Since 'a' is a string, it has the compareTo method which we call
           in MyClass's compareTo method.
        */

        return this.a.compareTo(someMyClass.a);

    }

    public static void main(String[] args){

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        if(object1.compareTo(object2) == 0){
            System.out.println("true");
        }
        else{
            System.out.println("false");
        }
    }
}

1

kiểu trả về của object.equals đã là boolean. không cần thiết phải quấn nó trong một phương pháp với các nhánh. vì vậy nếu bạn muốn so sánh 2 đối tượng chỉ cần so sánh chúng:

boolean b = objectA.equals(objectB);

b đã đúng hoặc sai.


1

Khi chúng ta sử dụng ==, Tham chiếu của đối tượng được so sánh không phải là các đối tượng thực tế. Chúng ta cần ghi đè phương thức bằng để so sánh các Đối tượng Java.

Một số thông tin bổ sung C ++ có toán tử quá tải và Java không cung cấp toán tử quá tải. Ngoài ra, các khả năng khác trong java là thực hiện Giao diện So sánh. Trong đó xác định phương thức CompareTo.

Giao diện so sánh cũng được sử dụng để so sánh hai đối tượng


4
Hãy cân nhắc rằng câu trả lời của bạn không bổ sung điều gì chưa được nói gần 2 năm trước.
Hot Licks

1

Ở đây kết quả đầu ra sẽ là false, báo hiệu sai trong câu lệnh sopln đầu tiên bạn đang cố gắng so sánh biến thể kiểu chuỗi của kiểu Myclass với kiểu MyClass khác và nó sẽ cho phép vì cả hai đều là kiểu Đối tượng và bạn đã sử dụng oprerator "==" mà sẽ kiểm tra giá trị biến tham chiếu giữ bộ nhớ thực không phải là liên kết thực bên trong bộ nhớ. Trong sopln thứ hai, nó cũng giống như bạn đang gọi a.equals (object2) trong đó a là một biến thể bên trong object1. Hãy cho tôi biết phát hiện của bạn về điều này.


2
Chào mừng bạn đến với bidyadhar stackoverflow. Câu hỏi đề ngày 14/11/2012 và đã được phản hồi tốt (được OP chấp thuận). Một trong những bạn nhận được là chính xác, nhưng nó không thêm thông tin hữu ích. Tôi đề nghị bạn đọc các quy tắc trước khi làm bất cứ điều gì
Nikaido

-3

TRONG đoạn mã dưới đây, bạn đang gọi phương thức ghi đè .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// ở đây bạn đang gọi phương thức overriden, đó là lý do tại sao bạn nhận được false 2 lần. trả về true; } else trả về false; }


1
Không, a.equalslà phương thức của chuỗi, nó không bị ghi đè ở bất kỳ đâu.
Tarec
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.