เปรียบเทียบสองวัตถุด้วยตัวดำเนินการ .equals () และ ==


85

ฉันสร้างคลาสที่มีStringฟิลด์เดียว จากนั้นฉันสร้างวัตถุสองชิ้นขึ้นมาและฉันต้องเปรียบเทียบโดยใช้==ตัวดำเนินการและ.equals()ด้วย นี่คือสิ่งที่ฉันทำ:

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));
    }


}

หลังจากคอมไพล์จะแสดงผลลัพธ์เป็นเท็จสองเท่า เหตุใดจึงเป็นเท็จถ้าวัตถุทั้งสองมีช่องเดียวกัน - "ทดสอบ"


7
Btw กำลังมองหาที่equalsและequals2เวลาที่คุณมีบางสิ่งบางอย่างในรูปแบบที่คุณควรอาจจะเพียงแค่เขียนif(a) { return true; } else { return false; } return a
yshavit

@yshavit คุณหมายถึงเปลี่ยนจากบูลีนเป็น String หรือไม่?
Fastkowy

4
ไม่รหัสของคุณกำลังถามว่าบูลีนเป็นจริงหรือไม่และจะส่งคืนtrueหากเป็นfalseเช่นนั้นหรือไม่ ตัวอย่างเช่นif(a.equals(object2)) { return true; } else return falseอาจเป็นreturn a.equals(object2)ได้
yshavit

คำตอบ:


142

==เปรียบเทียบอ้างอิงวัตถุมันจะตรวจสอบเพื่อดูว่าทั้งสองตัวถูกดำเนินการชี้ไปที่วัตถุเดียวกัน (ไม่เทียบเท่าวัตถุที่เดียวกันวัตถุ)

หากคุณต้องการเปรียบเทียบสตริง (เพื่อดูว่าพวกเขามีตัวอักษรเดียวกัน) equalsคุณจะต้องเปรียบเทียบสตริงโดยใช้

ในกรณีของคุณหากMyClassถือว่าสองอินสแตนซ์เท่ากันหากสตริงตรงกันแล้ว:

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

... แต่โดยปกติแล้วถ้าคุณกำลังกำหนดคลาสจะมีการเทียบเคียงมากกว่าการเทียบเท่าของฟิลด์เดียว ( aในกรณีนี้)


บันทึก Side: ถ้าคุณแทนที่คุณจะต้องเกือบเสมอที่จะแทนที่equals hashCodeตามที่กล่าวไว้ในequalsJavaDoc :

โปรดทราบว่าโดยทั่วไปจำเป็นต้องแทนที่hashCodeเมธอดเมื่อใดก็ตามที่เมธอดนี้ถูกแทนที่เพื่อรักษาสัญญาทั่วไปสำหรับhashCodeเมธอดซึ่งระบุว่าอ็อบเจ็กต์ที่เท่ากันต้องมีรหัสแฮชเท่ากัน


@TJ In == เปรียบเทียบการอ้างอิงอ็อบเจ็กต์เพื่ออธิบายอย่างละเอียดหมายความว่า == เปรียบเทียบแฮชโค้ดของทั้งสองอ็อบเจ็กต์หรือไม่?
Narendra Jaggi

@NarendraJaggi - ไม่หมายความว่า JVM จะตรวจสอบว่าตัวถูกดำเนินการทั้งสองอ้างถึงวัตถุเดียวกันหรือไม่ วิธีที่มันไม่ว่าขึ้นอยู่กับ JVM แต่มีเหตุผลที่จะคิดว่ามันจะใช้แฮชโค้ดที่จะทำมันไม่มี
TJ Crowder

19

คุณควรลบล้างเท่ากับ

 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
นี่เป็นคำตอบที่ดีที่สุด แต่คุณอาจต้องการใช้ this.equals (obj) แทน (this == null) สำหรับประเภทที่ไม่ใช่แบบดั้งเดิม
goonerify

10
ฉันขอยืนยันว่าif (this == null)กรณีนี้ไม่จำเป็นอยู่แล้ว การโทรnullObject.equals(whatever)กำลังจะทำให้เกิดข้อยกเว้นของตัวชี้ที่เป็นโมฆะดังนั้นเราสามารถสรุปได้อย่างปลอดภัยว่าthisไม่เป็นโมฆะในวิธีการใด ๆ ของ Java ที่เราอาจเขียนได้
Maura

5

ดูเหมือนequals2เป็นเพียงการโทรequalsดังนั้นมันจะให้ผลลัพธ์เหมือนกัน


1
OP เรียกequalsเมธอดของ String aซึ่งเป็นสมาชิกของคลาส equals2ไม่ได้โทรequals
Yigit Alparslan

1
ใช่ขอบคุณ. ดูเหมือนว่าฉันพลาดความสับสนระหว่าง MyClass และ String ซึ่งเป็นปัญหาที่แท้จริง
Hew Wolff

5

ฟังก์ชันเขียนทับเท่ากับ () ไม่ถูกต้อง อ็อบเจ็กต์ "a" เป็นอินสแตนซ์ของคลาสStringและ "object2" เป็นอินสแตนซ์ของคลาสMyClass พวกเขาเป็นคลาสที่แตกต่างกันดังนั้นคำตอบคือ "เท็จ"


5

วิธีที่ดีที่สุดในการเปรียบเทียบ 2 ออบเจ็กต์คือการแปลงเป็นสตริง json และเปรียบเทียบสตริงซึ่งเป็นวิธีที่ง่ายที่สุดเมื่อจัดการกับอ็อบเจ็กต์ที่ซ้อนกันซับซ้อนฟิลด์และ / หรืออ็อบเจ็กต์ที่มีอาร์เรย์

ตัวอย่าง:

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
ฉันต้องการเรียกสิ่งนี้ว่า overkill
Rolf ツ

@Rolf ツทำไมคุณถึงคิดแบบนี้มากเกินไป ฉันได้ค้นหาวิธีแก้ปัญหานี้แล้วและนี่เป็นวิธีแก้ปัญหาที่ง่ายที่สุดที่ฉันพบ ข้อเสนอแนะที่ดีกว่ายินดีต้อนรับ
m5seppal

3
เนื่องจากด้วย Java คุณสามารถเปรียบเทียบวัตถุได้โดยไม่ต้องสร้างGsonวัตถุก่อนแล้วจึงเรียกtoJsonใช้ การสร้างGsonวัตถุและการเรียกใช้ตรรกะที่จำเป็นในการแปลงวัตถุจริงเป็น flat String( toJson) เป็นค่าโสหุ้ยที่ไม่จำเป็น คุณสามารถเปรียบเทียบวัตถุโดยไม่ต้องแปลงวัตถุเป็นสตริง Json ก่อน (ซึ่งเร็วกว่าด้วย)
Rolf ツ

3

equals2()วิธีการของคุณจะกลับมาเหมือนเดิมเสมอequals()!!

รหัสของคุณพร้อมความคิดเห็นของฉัน:

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
เพียงreturn a.equals(object2);
mojuba

2

คำสั่งa == object2และ a.equals(object2)ทั้งสองจะกลับมาเสมอfalseเนื่องจากaเป็นstringwhile object2เป็นตัวอย่างของMyClass


2

การใช้งานของคุณต้องชอบ:

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

ด้วยการใช้งานทั้งสองวิธีนี้จะใช้ได้ผล


2

หากคุณไม่จำเป็นต้องปรับแต่งฟังก์ชัน toString () เริ่มต้นอีกวิธีหนึ่งคือการแทนที่ toString () วิธีการซึ่งจะส่งคืนแอตทริบิวต์ทั้งหมดที่จะเปรียบเทียบ จากนั้นเปรียบเทียบกับเอาต์พุต String () ของสองวัตถุ ฉันสร้าง toString () วิธีการโดยใช้ IntelliJ IDEA IDE ซึ่งรวมถึงชื่อคลาสในสตริง

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

ตัวดำเนินการ "==" จะส่งกลับค่าจริงก็ต่อเมื่อการอ้างอิงสองรายการชี้ไปที่วัตถุเดียวกันในหน่วยความจำ ในทางกลับกันวิธีการ equals () จะคืนค่าจริงตามเนื้อหาของวัตถุ

ตัวอย่าง:

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);

เอาต์พุต: การเปรียบเทียบสองสตริงด้วยตัวดำเนินการ ==: false การเปรียบเทียบสองสตริงที่มีเนื้อหาเดียวกันโดยใช้วิธีการเท่ากับ: จริงการเปรียบเทียบการอ้างอิงสองรายการที่ชี้ไปยังสตริงเดียวกันด้วยตัวดำเนินการ ==: จริง

คุณสามารถดูรายละเอียดเพิ่มเติมได้จากลิงค์: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2

ชั้นเรียนของคุณอาจใช้อินเทอร์เฟซที่เปรียบเทียบได้เพื่อให้สามารถใช้งานได้เหมือนกัน ชั้นเรียนของคุณควรใช้เมธอด CompareTo () ที่ประกาศไว้ในอินเทอร์เฟซ

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

ชนิดที่ส่งคืนของ object.equals เป็นบูลีนอยู่แล้ว ไม่จำเป็นต้องห่อด้วยกิ่งไม้ ดังนั้นหากคุณต้องการเปรียบเทียบ 2 วัตถุเพียงแค่เปรียบเทียบ:

boolean b = objectA.equals(objectB);

b เป็นจริงหรือเท็จ


1

เมื่อเราใช้ == การอ้างอิงของวัตถุจะถูกเปรียบเทียบไม่ใช่วัตถุจริง เราจำเป็นต้องแทนที่วิธีการเท่ากับเพื่อเปรียบเทียบ Java Objects

ข้อมูลเพิ่มเติมบางอย่าง C ++ มีตัวดำเนินการมากกว่าการโหลดและ Java ไม่ได้ให้ตัวดำเนินการในการโหลด ความเป็นไปได้อื่น ๆ ใน java คือใช้Compare Interfaceซึ่งกำหนดวิธีการ CompareTo

นอกจากนี้ยังใช้อินเทอร์เฟซตัวเปรียบเทียบเปรียบเทียบสองวัตถุ


4
พิจารณาว่าคำตอบของคุณไม่มีอะไรที่ไม่ได้พูดเมื่อเกือบ 2 ปีก่อน
Hot Licks

1

ที่นี่ผลลัพธ์จะเป็นเท็จเป็นเท็จในคำสั่ง sopln แรกคุณกำลังพยายามเปรียบเทียบประเภทสตริงที่แปรผันของประเภท Myclass กับประเภท MyClass อื่นและจะอนุญาตเนื่องจากทั้งสองเป็นประเภทวัตถุและคุณได้ใช้ตัวเลือก "==" ซึ่ง จะตรวจสอบค่าตัวแปรอ้างอิงที่ถือหน่วยความจำจริงไม่ใช่ contnets จริงภายในหน่วยความจำ ใน sopln ที่สองก็เหมือนกับที่คุณเรียกอีกครั้งว่า a.equals (object2) โดยที่ a เป็นตัวแปรภายใน object1 โปรดแจ้งให้เราทราบการค้นพบของคุณเกี่ยวกับเรื่องนี้


2
ยินดีต้อนรับสู่ stackoverflow bidyadhar คำถามคือวันที่ 14/11/2012 และได้รับการตอบรับที่ดี (อนุมัติโดย OP) สิ่งที่คุณได้รับนั้นถูกต้อง แต่ไม่ได้เพิ่มข้อมูลที่เป็นประโยชน์ ฉันขอแนะนำให้คุณอ่านกฎก่อนที่จะทำอะไร
Nikaido

-3

ในโค้ดด้านล่างนี้คุณกำลังเรียกใช้เมธอด overriden .equals ()

public boolean equals2 (Object object2) {if (a.equals (object2)) {// ที่นี่คุณกำลังเรียกใช้เมธอด overriden นั่นคือสาเหตุที่คุณได้รับเท็จ 2 ครั้ง กลับจริง; } else กลับเท็จ; }


1
ไม่a.equalsเป็นวิธีการของสตริงไม่ได้ลบล้างที่ใดก็ได้
Tarec
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.