อะไรคือความแตกต่างระหว่าง == และเท่ากับ () ใน Java?


622

ฉันต้องการชี้แจงหากฉันเข้าใจสิ่งนี้อย่างถูกต้อง:

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

43
ใช่สวยมาก
จอห์นเคน

9
ใช่เห็นด้วย คุณสามารถคิด.equals()เป็นเทียบเท่ามีความหมาย
vikingsteve


19
ประโยคเช่น "วัตถุทั้งสองชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน" เป็นภาษาที่เลอะเทอะซึ่งสามารถทำให้เข้าใจยากขึ้น คุณหมายถึง: "ตัวแปรทั้งสองอ้างถึงวัตถุเดียวกัน" โปรดทราบว่าตัวแปรไม่ใช่วัตถุ ตัวแปรคือการอ้างอิงไปยังวัตถุ วัตถุไม่ "ชี้ไปที่" อะไรเลย
Jesper

คำตอบ:


625

โดยทั่วไปคำตอบสำหรับคำถามของคุณคือ "ใช่" แต่ ...

  • .equals(...) จะเปรียบเทียบสิ่งที่เขียนเพื่อเปรียบเทียบไม่มากไม่น้อยไป
  • ถ้าคลาสไม่ได้แทนที่เมธอด equals คลาสนั้นจะใช้equals(Object o)เมธอดของคลาสพาเรนต์ที่ใกล้เคียงที่สุดซึ่งแทนที่เมธอดนี้
  • หากไม่มีคลาสพาเรนต์ที่ได้จัดเตรียมการแทนที่ไว้ค่าเริ่มต้นจะเป็นเมธอดจากคลาสพาเรนต์สูงสุด Object และดังนั้นคุณจึงเหลือObject#equals(Object o)วิธีดังกล่าว สำหรับ Object API นี้จะเหมือนกับ==; นั่นคือมันจะคืนค่าจริงถ้าหากทั้งสองตัวแปรอ้างถึงวัตถุเดียวกันหากการอ้างอิงของพวกเขาเป็นหนึ่งและเหมือนกัน ดังนั้นคุณจะได้รับการทดสอบความเสมอภาควัตถุและไม่เท่าเทียมกันทำงาน
  • โปรดอย่าลืมแทนที่hashCodeหากคุณแทนที่equalsเพื่อไม่ให้ "ผิดสัญญา" ตาม API ผลลัพธ์ที่ส่งคืนจากhashCode()เมธอดสำหรับสองอ็อบเจ็กต์ต้องเหมือนกันถ้าequalsเมธอดของพวกเขาแสดงว่าเทียบเท่า การสนทนาไม่จำเป็นต้องเป็นเรื่องจริง

หาก==ตรวจสอบการอ้างอิงหน่วยความจำแล้วทำไมฉันถึงได้รับพฤติกรรมแปลก ๆ นี้ใน [นี่] [1] [1]: docs.google.com/document/d/… ฉันคาดว่าผลลัพธ์จะเป็นจริง สามารถล้างความสับสนของฉัน
JPG

4
@JSK พิมพ์ค่าของ d1 และ d2 และฉันคิดว่าคุณจะเห็นว่าทำไมคุณถึงกลับเท็จ
BoDidely

2
@BoDidely ฉันคิดออก มันเป็นเพราะคลาสของ wrapper นั้นไม่เปลี่ยนรูป
JPG

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).<br/> Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.( docs.oracle.com/javase/7/docs/api/java/lang/… )
Abhijeet

ไม่เกี่ยวข้อง: วันนี้ฉันวางคำถามเมตา ( meta.stackoverflow.com/questions/372795/ … ) เกี่ยวกับข้อความดี / มีประสิทธิภาพ / ... "อัตโนมัติ" เมื่อแสดงความคิดเห็นคำถามที่มีคุณภาพต่ำ คำติชมที่ฉันได้รับรู้สึกค่อนข้างมาก "คุณกำลังทำสิ่งที่ผิดทั้งหมด" ตอนนี้ฉันแค่สงสัยว่าคุณดูที่นี้ได้อย่างไร คุณมีข้อความ "ทั่วไป" ในตัวสั่นหรือคุณเขียนเฉพาะความคิดเห็นในกรณีเช่นนี้หรือไม่?
GhostCat

107

ด้วยความเคารพคลาส String:

เท่ากับ () วิธีการเปรียบเทียบ "คุณค่า" ในกรณีสตริง (ในกอง) โดยไม่คำนึงถึงถ้าสองอ้างอิงวัตถุอ้างถึงเช่น String เดียวกันหรือไม่ ถ้ามีวัตถุสองชนิดที่อ้างอิงถึง String ชนิดอ้างอิงถึงอินสแตนซ์สตริงเดียวกันนั้นยอดเยี่ยม! หากการอ้างอิงวัตถุทั้งสองอ้างถึงสองอินสแตนซ์ของสตริงที่แตกต่างกัน .. มันไม่ได้สร้างความแตกต่าง มันคือ "คุณค่า" (นั่นคือ: เนื้อหาของอาร์เรย์อักขระ) ภายในแต่ละอินสแตนซ์ของสตริงที่จะถูกเปรียบเทียบ

บนมืออื่น ๆ ที่ "==" ผู้ประกอบการเปรียบเทียบค่าของสองอ้างอิงวัตถุเพื่อดูว่าพวกเขาอ้างถึงเดียวกันเช่น String หากค่าของการอ้างอิงวัตถุทั้งสอง "อ้างอิงถึง" อินสแตนซ์ของสตริงเดียวกันผลลัพธ์ของนิพจน์บูลีนจะเป็น "true" .. duh หากในทางกลับกันค่าของการอ้างอิงวัตถุทั้งสอง "อ้างอิงถึง" อินสแตนซ์ของสตริงที่แตกต่างกัน (แม้ว่าทั้งสองอินสแตนซ์ของสตริงมี "ค่า" เหมือนกันนั่นคือเนื้อหาของอาร์เรย์อักขระของแต่ละอินสแตนซ์ของสตริงจะเหมือนกัน) ผลลัพธ์ของนิพจน์บูลีนจะเป็น "false"

เช่นเดียวกับคำอธิบายใด ๆ ปล่อยให้มันจมลงมา

ฉันหวังว่าสิ่งนี้จะช่วยล้างสิ่งเล็กน้อย


1
ดังนั้นสำหรับสตริง == เท่ากับการอ้างอิงเช่นกัน? เช่นทำงานเช่นเดียวกับวัตถุอื่น ๆ ?
JonnyRaa

2
(เวทมนตร์กระทู้ฉันรู้ ... ) สำหรับStrings, ==อ้างอิงเท่ากับเป็นอย่างดีใช่ แต่มันมักจะทำงาน (ในขณะที่ทั้งสองStringกำลังมีเนื้อหาเดียวกันจะมักจะเป็น==กับแต่ละอื่น ๆ ) เนื่องจากวิธีการจับ Java Strings มันจะไม่เสมอไปและเป็นการฝึกฝนที่ไม่ดีอย่างแน่นอน แต่เป็นความผิดพลาดทั่วไปโดยเฉพาะอย่างยิ่งจากผู้ที่มาจากภาษาอื่น
Tonio

7
เพื่อเพิ่มความคิดเห็นของ Tonio Stringสร้างจากสตริงตัวอักษรจะถูกเพิ่มลงในสิ่งที่เรียกว่าString constant poolเช่นString s1 = "someString"; String s2 = "someString;"ทั้งสองs1และs2จะแบ่งปันการอ้างอิงเดียวกัน s1 == s2จะกลับมาจริง แต่ถ้าพวกเขาถูกสร้างขึ้นผ่านทางString constructorเช่นString s1 = new String("someString"); String s2 = new String("someString");พวกเขาจะไม่แบ่งปันการอ้างอิงเดียวกัน s1 == s2จะกลับเท็จ
กาวิน

61

มีความแตกต่างเล็กน้อยขึ้นอยู่กับว่าคุณกำลังพูดถึง "ดั้งเดิม" หรือ "ประเภทวัตถุ"; เดียวกันสามารถพูดได้ถ้าคุณกำลังพูดถึงสมาชิก "คงที่" หรือ "ไม่คงที่"; คุณสามารถผสมทั้งหมดข้างต้น ...

นี่คือตัวอย่าง (คุณสามารถเรียกใช้):

public final class MyEqualityTest
{
    public static void main( String args[] )
    {
        String s1 = new String( "Test" );
        String s2 = new String( "Test" );

        System.out.println( "\n1 - PRIMITIVES ");
        System.out.println( s1 == s2 ); // false
        System.out.println( s1.equals( s2 )); // true

        A a1 = new A();
        A a2 = new A();

        System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
        System.out.println( a1 == a2 ); // false
        System.out.println( a1.s == a2.s ); // true
        System.out.println( a1.s.equals( a2.s ) ); // true

        B b1 = new B();
        B b2 = new B();

        System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
        System.out.println( b1 == b2 ); // false
        System.out.println( b1.getS() == b2.getS() ); // false
        System.out.println( b1.getS().equals( b2.getS() ) ); // true
    }
}

final class A
{
    // static
    public static String s;
    A()
    {
        this.s = new String( "aTest" );
    }
}

final class B
{
    private String s;
    B()
    {
        this.s = new String( "aTest" );
    }

    public String getS()
    {
        return s;
    }

}

คุณสามารถเปรียบเทียบคำอธิบายสำหรับ "==" (Equality Operator) และ ".equals (... )" (เมธอดในคลาส java.lang.Object) ผ่านลิงก์เหล่านี้:


2
ตัวอย่างที่น่าสนใจ มุมมองที่แตกต่างจากคำตอบข้างต้น ขอบคุณ!
Andrew

1
คำตอบที่ดีที่สุดในความคิดของฉันเพราะมันชัดเจนกว่าคำตอบแบบเต็มอื่น ๆ โดยไม่สูญเสียคำอธิบาย (ถ้าคุณดำเนินการชั้นเรียนและแนวคิดคงที่แน่นอน)
Carrm

44

ความแตกต่างระหว่าง == และเท่ากับทำให้ฉันสับสนในบางครั้งจนกระทั่งฉันตัดสินใจที่จะมองใกล้ ๆ หลายคนบอกว่าสำหรับการเปรียบเทียบสตริงคุณควรใช้และไม่ได้equals ==หวังว่าในคำตอบนี้ฉันจะสามารถพูดความแตกต่าง

วิธีที่ดีที่สุดในการตอบคำถามนี้คือการถามคำถามกับตัวเอง เริ่มกันเลย:

ผลลัพธ์สำหรับโปรแกรมด้านล่างคืออะไร:

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

ถ้าคุณพูด,

false
true

ฉันจะบอกว่าคุณพูดถูกแต่ทำไมคุณถึงพูดอย่างนั้น ? และถ้าคุณบอกว่าผลลัพธ์คือ

true
false

ฉันจะบอกว่าคุณคิดผิดแต่ฉันจะถามคุณทำไมคุณคิดว่าถูกต้อง?

ตกลงลองตอบคำถามนี้:

ผลลัพธ์สำหรับโปรแกรมด้านล่างคืออะไร:

String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);

ตอนนี้ถ้าคุณพูดว่า

false
true

ฉันจะบอกว่าคุณผิดแต่ทำไมตอนนี้ผิด ? ผลลัพธ์ที่ถูกต้องสำหรับโปรแกรมนี้คือ

true
false

โปรดเปรียบเทียบโปรแกรมด้านบนและลองคิดดู

ตกลง. ตอนนี้สิ่งนี้อาจช่วยได้ (โปรดอ่านสิ่งนี้: พิมพ์ที่อยู่ของวัตถุ - เป็นไปไม่ได้ แต่เรายังสามารถใช้งานได้)

String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);

System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));

คุณสามารถลองคิดถึงผลลัพธ์ของสามบรรทัดสุดท้ายในรหัสด้านบน: สำหรับฉัน ideone พิมพ์ออกมา ( คุณสามารถตรวจสอบรหัสที่นี่ ):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

Oh! ตอนนี้คุณเห็นidentityHashCode (มะม่วง) เท่ากับ identityHashCode (mango2) แต่มันไม่เท่ากับ identityHashCode (mango3)

แม้ว่าตัวแปรสตริงทั้งหมด - mango, mango2 และ mango3 - มีค่าเดียวกันซึ่งก็คือ "mango" identityHashCode()ยังคงไม่เหมือนเดิมสำหรับทุกคน

ทีนี้ลองยกเลิกการใส่เครื่องหมายบรรทัดนี้// mango2 = "mang";แล้วเปิดใหม่อีกครั้งคราวนี้คุณจะเห็นทั้งสามอย่างidentityHashCode()แตกต่าง อืมนั่นเป็นคำใบ้ที่มีประโยชน์

เรารู้ว่าถ้าhashcode(x)=Nและhashcode(y)=N=>x is equal to y

ฉันไม่แน่ใจว่า java ทำงานอย่างไรภายใน แต่ฉันคิดว่านี่เป็นสิ่งที่เกิดขึ้นเมื่อฉันพูดว่า:

mango = "mango";

java สร้างสตริง"mango"ที่ชี้ (อ้างอิง) โดยตัวแปรmangoบางอย่างเช่นนี้

mango ----> "mango"

ตอนนี้อยู่ในบรรทัดถัดไปเมื่อฉันพูดว่า:

mango2 = "mango";

จริง ๆ แล้วมันใช้ซ้ำสายเดียวกัน"mango"ซึ่งมีลักษณะดังนี้

mango ----> "mango" <---- mango2

ทั้งมะม่วงและมะม่วง 2 ชี้ไปที่การอ้างอิงเดียวกันตอนนี้เมื่อฉันพูด

mango3 = new String("mango")

มันสร้างการอ้างอิงใหม่ (สตริง) สำหรับ "มะม่วง" โดยสมบูรณ์ ซึ่งมีลักษณะเช่นนี้

mango -----> "mango" <------ mango2

mango3 ------> "mango"

และที่ว่าทำไมเมื่อฉันใส่ออกค่าสำหรับมันใส่ออกmango == mango2 trueและเมื่อฉันใส่ค่าสำหรับmango3 == mango2มันก็จะดับfalse(แม้เมื่อค่าเหมือนกัน)

และเมื่อคุณไม่ใส่เครื่องหมายในบรรทัด// mango2 = "mang"; มันสร้างสตริง "mang" ซึ่งเปลี่ยนกราฟของเราดังนี้:

mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"

นี่คือเหตุผลที่ identityHashCode ไม่เหมือนกันสำหรับทุกคน

หวังว่านี่จะช่วยพวกคุณได้ ที่จริงแล้วฉันต้องการที่จะสร้างกรณีทดสอบที่ == ล้มเหลวและเท่ากับ () ผ่าน โปรดแสดงความคิดเห็นและแจ้งให้เราทราบหากฉันผิด


ที่ไม่mango == mango2เกิดขึ้นเพราะคุณไม่ได้สร้างmango2 เป็นวัตถุใหม่ String และแทนที่จะอ้างอิงเพียงโดยตรง"mango"?
brt

1
ตัวอย่างที่ไม่ถูกต้องในการใช้ String เพื่อล้างข้อสงสัยใน == และเท่ากับ String เมื่อไม่ได้ใช้กับใหม่จะถูกใส่ลงใน String Pool และเมื่อใดก็ตามที่สตริงเดียวกันถูกกำหนดให้กับการอ้างอิงใหม่มันจะชี้ไปที่สตริงเดียวกันในพูล ดังนั้นอาจใช้ตัวอย่างวัตถุที่กำหนดเองสำหรับการเปรียบเทียบ == และ. equals ()
om252345

30

==ทดสอบผู้ประกอบการไม่ว่าจะเป็นตัวแปรทั้งสองมีการอ้างอิงเดียวกัน (หรือที่รู้จักตัวชี้ไปยังที่อยู่หน่วยความจำ)

String foo = new String("abc");
String bar = new String("abc");

if(foo==bar)
// False (The objects are not the same)

bar = foo;

if(foo==bar)
// True (Now the objects are the same)

ในขณะที่วิธีequals ()จะทดสอบว่าตัวแปรสองตัวอ้างถึงวัตถุที่มีสถานะ (ค่าเดียวกัน)หรือไม่

String foo = new String("abc");
String bar = new String("abc");

if(foo.equals(bar))
// True (The objects are identical but not same)

ไชโย :-)


1
ไม่ถูกต้อง. ถ้า (foo == bar) สิ่งนี้ควรเป็นจริงไม่ใช่เท็จ มันจะใช้สตริง "adc" ซ้ำ ทดสอบในกล่องทรายมันจะกลับมาเป็นจริงสำหรับทั้งคู่
Johnathan Logan

2
@JohnathanLogan ฉันเดาว่ามันเป็นเพราะการฝึกงานสตริง ตอนนี้ฉันเปลี่ยนเป็น "new String (" abc ")" หวังว่าตอนนี้จะไม่มีปัญหาใด ๆ ขอขอบคุณที่แจ้ง
Mohanraj Balasubramaniam

13

คุณจะต้องแทนที่ฟังก์ชั่นเท่ากับ (พร้อมกับคนอื่น ๆ ) เพื่อใช้กับคลาสที่กำหนดเอง

วิธีการที่เท่าเทียมกันเปรียบเทียบวัตถุ

ตัว==ดำเนินการไบนารีเปรียบเทียบที่อยู่หน่วยความจำ


8

ทั้ง == และ. equals () อ้างถึงวัตถุเดียวกันหากคุณไม่ได้แทนที่. equals ()

เป็นความปรารถนาของคุณในสิ่งที่คุณต้องการทำเมื่อคุณแทนที่. equals () คุณสามารถเปรียบเทียบสถานะของวัตถุที่กล่าวอ้างกับสถานะส่งผ่านในวัตถุหรือคุณสามารถเรียก super.equals ()


7

==เป็นผู้ประกอบการและequals()เป็นวิธีการ

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


6
 String w1 ="Sarat";
 String w2 ="Sarat";
 String w3 = new String("Sarat");

 System.out.println(w1.hashCode());   //3254818
 System.out.println(w2.hashCode());   //3254818
 System.out.println(w3.hashCode());   //3254818

 System.out.println(System.identityHashCode(w1)); //prints 705927765
 System.out.println(System.identityHashCode(w2)); //prints 705927765
 System.out.println(System.identityHashCode(w3)); //prints 366712642


 if(w1==w2)   //  (705927765==705927765)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true

 if(w2==w3)   //  (705927765==366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints false


 if(w2.equals(w3))   //  (Content of 705927765== Content of 366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true

คำอธิบายที่ง่ายและดีที่สุด
Sritam Jagadev

5

เพียงจำไว้ว่า.equals(...)ต้องนำไปใช้กับชั้นเรียนที่คุณพยายามเปรียบเทียบ มิฉะนั้นจะมีจุดไม่มาก รุ่นของวิธีการสำหรับการเรียนวัตถุที่จะเป็นสิ่งเดียวกับการดำเนินการเปรียบเทียบ: วัตถุ # เท่าเทียมกัน

ครั้งเดียวที่คุณต้องการใช้ตัวดำเนินการเปรียบเทียบสำหรับวัตถุคือเมื่อคุณเปรียบเทียบ Enums นี่เป็นเพราะมีเพียงหนึ่งอินสแตนซ์ของค่า Enum ในแต่ละครั้ง ตัวอย่างเช่นกำหนด enum

enum FooEnum {A, B, C}

คุณจะไม่เคยมีมากกว่าหนึ่งตัวอย่างของAที่เวลาและเหมือนกันสำหรับและB Cซึ่งหมายความว่าคุณสามารถเขียนวิธีการเช่น:

public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}

และคุณจะไม่มีปัญหาใด ๆ


4

เมื่อคุณประเมินโค้ดมันชัดเจนมากว่า (==) เปรียบเทียบตามที่อยู่หน่วยความจำในขณะที่เท่ากับ (Object o) เปรียบเทียบ hashCode () ของอินสแตนซ์ นั่นคือเหตุผลที่ว่ากันว่าอย่าทำลายสัญญาระหว่าง equals () และ hashCode () ถ้าคุณไม่เผชิญกับความประหลาดใจในภายหลัง

    String s1 = new String("Ali");
    String s2 = new String("Veli");
    String s3 = new String("Ali");

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());


    System.out.println("(s1==s2):" + (s1 == s2));
    System.out.println("(s1==s3):" + (s1 == s3));


    System.out.println("s1.equals(s2):" + (s1.equals(s2)));
    System.out.println("s1.equal(s3):" + (s1.equals(s3)));


    /*Output 
    96670     
    3615852
    96670
    (s1==s2):false
    (s1==s3):false
    s1.equals(s2):false
    s1.equal(s3):true
    */

4

นี่คือนิ้วหัวแม่มือทั่วไปของกฎสำหรับความแตกต่างระหว่างและrelational operator ==the method .equals()

object1 == object2เปรียบเทียบถ้าวัตถุอ้างอิงโดย object1 และ object2 อ้างถึง t เขาตั้งหน่วยความจำเดียวกันในกอง

object1.equals(object2)เปรียบเทียบค่าของ object1 และ object2 โดยไม่คำนึงถึงที่พวกเขาอยู่ในหน่วยความจำ

สิ่งนี้สามารถแสดงให้เห็นได้ดีโดยใช้ String

สถานการณ์ 1

 public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = new String("Hello");
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

 }



The result is
      is str1 == str2 ? false
      is str1.equals(str2) ? true 

สถานการณ์ที่ 2

public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = "Hello";
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

}

The result is 
  is str1 == str2 ? true
  is str1.equals(str2) ? true

การเปรียบเทียบสตริงนี้สามารถใช้เป็นพื้นฐานสำหรับการเปรียบเทียบวัตถุประเภทอื่น

ตัวอย่างเช่นถ้าฉันมีชั้นคนที่ฉันจำเป็นต้องกำหนดฐานเกณฑ์ที่ผมจะเปรียบเทียบคนสองคน สมมุติว่าคลาสบุคคลนี้มีตัวแปรอินสแตนซ์ของความสูงและน้ำหนัก

ดังนั้นการสร้างวัตถุบุคคลperson1 and person2และสำหรับการเปรียบเทียบทั้งสองนี้โดยใช้.equals()ฉันจำเป็นต้องแทนที่วิธีการที่เท่าเทียมกันของระดับบุคคลเพื่อกำหนดตามตัวแปรอินสแตนซ์ (heigh หรือน้ำหนัก) การเปรียบเทียบจะเป็น

== operator will still return results based on the memory location of the two objects(person1 and person2)อย่างไรก็ตาม

เพื่อความสะดวกในการทำให้การเปรียบเทียบวัตถุบุคคลนี้เป็นเรื่องง่ายฉันได้สร้างคลาสทดสอบต่อไปนี้ การทดลองแนวคิดเหล่านี้จะเปิดเผยข้อเท็จจริงมากมาย

package com.tadtab.CS5044;

public class Person {

private double height;
private double weight;

public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public double getWeight() {
    return weight;
}

public void setWeight(double weight) {
    this.weight = weight;
}


@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(height);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
/**
 * This method uses the height as a means of comparing person objects.
 * NOTE: weight is not part of the comparison criteria
 */
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
        return false;
    return true;
}

public static void main(String[] args) {

    Person person1 = new Person();
    person1.setHeight(5.50);
    person1.setWeight(140.00);

    Person person2 = new Person();
    person2.setHeight(5.70);
    person2.setWeight(160.00);

    Person person3 = new Person();
    person3 = person2;

    Person person4 = new Person();
    person4.setHeight(5.70);

    Person person5 = new Person();
    person5.setWeight(160.00);

    System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
    System.out.println("is person2 == person3 ? " + (person2 == person3)); // true 
    //this is because perosn3 and person to refer to the one person object in memory. They are aliases;
    System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;

    System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;

    // even if the person2 and person5 have the same weight, they are not equal.
    // it is because their height is different
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}

}

ผลลัพธ์ของการดำเนินคลาสนี้คือ:

is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false

3

โปรดทราบว่า.equals()โดยปกติจะมี==การทดสอบเนื่องจากนี่เป็นสิ่งแรกที่คุณต้องการทดสอบหากคุณต้องการทดสอบว่าวัตถุสองรายการเท่ากันหรือไม่

และ==จริง ๆ แล้วดูที่ค่าสำหรับชนิดดั้งเดิมสำหรับวัตถุนั้นตรวจสอบการอ้างอิง


3

== โอเปอเรเตอร์ที่อ้างอิงเสมอจะถูกเปรียบเทียบ แต่ในกรณีของ

เท่ากับ () วิธีการ

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

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//fasle
      obj==obj1 // fasle
    }
 }

ในโค้ดข้างต้นทั้งวัตถุ obj และ obj1 มีข้อมูลเดียวกัน แต่การอ้างอิงไม่เหมือนกันดังนั้นเท่ากับ return false และ == ด้วย แต่ถ้าเราแทนที่เมธอดเท่ากับวิธีกว่า

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }
    public boolean equals(Object obj)
    {
       A a1=(A)obj;
      return this.id==a1.id;
    }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//true
      obj==obj1 // fasle
    }
 }

รู้ว่ามันจะกลับมาจริงและเท็จสำหรับกรณีเดียวกันเท่านั้นที่เราแทนที่

เท่ากับวิธีการ

มันเปรียบเทียบวัตถุบนพื้นฐานของเนื้อหา (id) ของวัตถุ

แต่ ==

ยังคงเปรียบเทียบการอ้างอิงของวัตถุ


3

ความแตกต่างที่สำคัญระหว่าง == และเท่ากับ () คือ

1) == ใช้ในการเปรียบเทียบแบบดั้งเดิม

ตัวอย่างเช่น :

        String string1 = "Ravi";
        String string2 = "Ravi";
        String string3 = new String("Ravi");
        String string4 = new String("Prakash");

        System.out.println(string1 == string2); // true because same reference in string pool
        System.out.println(string1 == string3); // false

2) equals () ใช้เพื่อเปรียบเทียบวัตถุ ตัวอย่างเช่น :

        System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
        System.out.println(string1.equals(string3)); // true
        System.out.println(string1.equals(string4)); // false

2

==สามารถใช้ได้กับวัตถุหลายประเภท แต่คุณสามารถใช้ได้Object.equalsกับทุกประเภทโดยเฉพาะอย่างยิ่ง Strings และ Google Map Markers


2
public class StringPool {

public static void main(String[] args) {

    String s1 = "Cat";// will create reference in string pool of heap memory
    String s2 = "Cat";
    String s3 = new String("Cat");//will create a object in heap memory

    // Using == will give us true because same reference in string pool

    if (s1 == s2) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using == with reference and Object will give us False

    if (s1 == s3) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using .equals method which refers to value

    if (s1.equals(s3)) {
        System.out.println("true");
    } else {
        System.out.println("False");
    }

    }
  }

---- เอาท์พุท ----- จริงเท็จจริง


2

มันอาจจะคุ้มที่จะเพิ่มว่าสำหรับวัตถุห่อหุ้มสำหรับประเภทดั้งเดิม - เช่น Int, Long, Double - == จะกลับมาจริงถ้าทั้งสองค่าเท่ากัน

Long a = 10L;
Long b = 10L;

if (a == b) {
    System.out.println("Wrapped primitives behave like values");
}

ในการเปรียบเทียบการวาง Longs สองรายการด้านบนเป็น ArrayLists ที่แยกกันสองรายการเท่ากับเห็นว่าเหมือนกัน แต่ == ไม่

ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();

c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");

วัตถุแรปเปอร์สำหรับประเภทดั้งเดิม - เช่น Integer, Long, Double == อาจไม่ส่งคืนจริงแม้ว่าค่าทั้งสองจะเท่ากัน มันขึ้นอยู่กับแคชของ Wrapper เท่านั้น โค้ดด้านล่างจะพิมพ์เท็จเนื่องจากแคชเริ่มต้นถูก จำกัด ที่ -128 ถึง 127 Long a = 128l; Long b = 128l; System.out.println(a == b);
Neetesh Bhardwaj

1

The String pool (aka interning ) และInteger poolเบลอความแตกต่างเพิ่มเติมและอาจทำให้คุณสามารถใช้==สำหรับวัตถุในบางกรณีแทน.equals

สิ่งนี้สามารถเพิ่มประสิทธิภาพให้กับคุณได้มากขึ้น (?) ด้วยต้นทุนของความซับซ้อนที่มากขึ้น

เช่น:

assert "ab" == "a" + "b";

Integer i = 1;
Integer j = i;
assert i == j;

ความซับซ้อนของการแลกเปลี่ยน: สิ่งต่อไปนี้อาจทำให้คุณประหลาดใจ:

assert new String("a") != new String("a");

Integer i = 128;
Integer j = 128;
assert i != j;

ฉันแนะนำให้คุณหลีกเลี่ยงการเพิ่มประสิทธิภาพขนาดเล็กเช่นนี้และใช้สำหรับวัตถุเสมอ.equalsและ==สำหรับการใช้พื้นฐาน:

assert (new String("a")).equals(new String("a"));

Integer i = 128;
Integer j = 128;
assert i.equals(j);

1

ในระยะสั้นคำตอบคือ "ใช่"

ใน Java ==ผู้ประกอบการเปรียบเทียบวัตถุทั้งสองเพื่อดูว่าพวกเขาชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน; ในขณะที่.equals()วิธีการเปรียบเทียบวัตถุทั้งสองจริง ๆ เพื่อดูว่าพวกเขามีค่าวัตถุเดียวกัน


0

โดยทั่วไปให้==เปรียบเทียบว่าวัตถุสองชิ้นมีการอ้างอิงเดียวกันกับฮีปดังนั้นหากการอ้างอิงสองรายการเชื่อมโยงกับวัตถุเดียวกันการเปรียบเทียบนี้จะเป็นเท็จ

equals()เป็นวิธีการสืบทอดจากObjectชั้นเรียน วิธีการนี้โดยค่าเริ่มต้นจะเปรียบเทียบหากวัตถุสองรายการมีการอ้างอิงเดียวกัน มันหมายถึง:

object1.equals(object2) <=> object1 == object2

อย่างไรก็ตามหากคุณต้องการสร้างความเท่าเทียมกันระหว่างสองวัตถุของคลาสเดียวกันคุณควรจะแทนที่วิธีนี้ ยังเป็นสิ่งสำคัญมากที่จะแทนที่วิธีhashCode()หากคุณมี equals()overriden

ใช้งานhashCode()เมื่อสร้างความเท่าเทียมกันเป็นส่วนหนึ่งของสัญญา Java Object หากคุณกำลังทำงานกับคอลเล็กชันและคุณยังไม่ได้ใช้งานhashCode()สิ่งแปลก ๆ อาจเกิดขึ้น

HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));

nullhashCode()จะถูกพิมพ์หลังจากรันรหัสก่อนหน้านี้ถ้าคุณยังไม่ได้ดำเนินการ


0

เนื่องจาก Java ไม่รองรับการโอเวอร์โหลดของผู้ให้บริการ == มีพฤติกรรมเหมือนกันสำหรับทุกวัตถุ แต่ equals () เป็นวิธีการซึ่งสามารถแทนที่ได้ใน Java และตรรกะเพื่อเปรียบเทียบวัตถุที่สามารถเปลี่ยนแปลงได้ตามกฎทางธุรกิจ

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

การเปรียบเทียบสตริงเป็นสถานการณ์ทั่วไปของการใช้ทั้งวิธี == และเท่ากับ ตั้งแต่ java.lang.String การแทนที่คลาสเท่ากับเมธอดมันจะคืนค่าจริงถ้าวัตถุ String สองตัวมีเนื้อหาเดียวกัน แต่ == จะคืนค่าจริงถ้าการอ้างอิงสองรายการชี้ไปที่วัตถุเดียวกัน

นี่คือตัวอย่างของการเปรียบเทียบสอง Strings ใน Java เพื่อความเท่าเทียมกันโดยใช้วิธีการ == และ equals () ซึ่งจะเคลียร์ข้อสงสัยบางอย่าง:

public class TEstT{

    public static void main(String[] args) {

String text1 = new String("apple");
String text2 = new String("apple");

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

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

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

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