ความแตกต่างระหว่าง==และ.equals()ในสกาล่าคืออะไรและเมื่อใดควรใช้อันไหน
การใช้งานเหมือนกับใน Java หรือไม่?
แก้ไข: AnyValคำถามที่เกี่ยวข้องกับการเจรจาเกี่ยวกับกรณีที่เฉพาะเจาะจงของ Anyกรณีทั่วไปมากขึ้นคือ
ความแตกต่างระหว่าง==และ.equals()ในสกาล่าคืออะไรและเมื่อใดควรใช้อันไหน
การใช้งานเหมือนกับใน Java หรือไม่?
แก้ไข: AnyValคำถามที่เกี่ยวข้องกับการเจรจาเกี่ยวกับกรณีที่เฉพาะเจาะจงของ Anyกรณีทั่วไปมากขึ้นคือ
คำตอบ:
ปกติคุณจะใช้==มันจะนำไปสู่การequalsยกเว้นว่าจะปฏิบัติต่อnullอย่างถูกต้อง ความเสมอภาคอ้างอิง (ไม่ค่อยได้ใช้) eqเป็น
3 == BigInt(3)และBigInt(3) == 3เป็นจริง แต่3.equals(BigInt(3))เป็นเท็จในขณะที่BigInt(3).equals(3)เป็นจริง ==ดังนั้นชอบใช้ หลีกเลี่ยงการใช้equals()ในสกาล่า ฉันคิดว่า==การแปลงโดยนัยทำได้ดี แต่equals()ทำไม่ได้
new java.lang.Integer(1) == new java.lang.Double(1.0)เป็นจริงในขณะที่new java.lang.Integer(1) equals new java.lang.Double(1.0)เป็นเท็จ
==เป็นวิธีสุดท้ายและการโทร.equalsซึ่งไม่ใช่วิธีสุดท้าย
สิ่งนี้แตกต่างอย่างสิ้นเชิงจาก Java ซึ่ง==เป็นตัวดำเนินการแทนที่จะเป็นวิธีการและเปรียบเทียบความเท่าเทียมกันของการอ้างอิงสำหรับวัตถุอย่างเคร่งครัด
equalsวิธีการเพื่อเปรียบเทียบเนื้อหาของแต่ละอินสแตนซ์ นี่เป็นequalsวิธีเดียวกับที่ใช้ใน Java==โอเปอเรเตอร์เพื่อเปรียบเทียบโดยไม่ต้องกังวลกับnullการอ้างอิงeqวิธีการตรวจสอบว่าข้อโต้แย้งทั้งสองตรงอ้างอิงเดียวกัน ไม่แนะนำให้ใช้จนกว่าคุณจะเข้าใจวิธีการทำงานและมักequalsจะทำงานในสิ่งที่คุณต้องการแทน และให้แน่ใจว่าจะใช้เฉพาะกับAnyRefข้อโต้แย้งไม่ใช่เพียงAnyหมายเหตุ: ในกรณีของequalsเช่นเดียวกับใน Java มันอาจไม่ส่งกลับผลลัพธ์เดียวกันถ้าคุณเปลี่ยนอาร์กิวเมนต์เช่น1.equals(BigInt(1))จะกลับfalseที่ผกผันจะกลับมาtrueที่ผกผันจะกลับมานี่เป็นเพราะการตรวจสอบการใช้งานแต่ละประเภทเท่านั้น หมายเลขดั้งเดิมไม่ตรวจสอบว่าอาร์กิวเมนต์ที่สองเป็นแบบNumberหรือBigIntแบบ แต่มีประเภทแบบดั้งเดิมเท่านั้น
AnyRef.equals(Any)วิธีการเป็นหนึ่งแทนที่โดย subclasses วิธีการจากข้อกำหนดของจาวาที่มาถึง Scala ด้วย หากใช้กับอินสแตนซ์ที่ไม่ได้ทำกล่องจะถูกเรียกให้เรียกสิ่งนี้ (แม้ว่าจะซ่อนอยู่ใน Scala แต่จะชัดเจนกว่าใน Java ด้วยint->Integer ) การใช้งานเริ่มต้นเพียงเปรียบเทียบการอ้างอิง (เช่นใน Java)
Any.==(Any)วิธีการเปรียบเทียบสองวัตถุและช่วยให้การโต้แย้งใดอย่างหนึ่งเพื่อเป็นโมฆะ (เช่นถ้าเรียกวิธีคงมีสองกรณี) มันเปรียบเทียบว่าทั้งคู่เป็นแบบnullนั้นequals(Any)หรือเปล่าแล้วมันจะเรียกเมธอดบนอินสแตนซ์ของกล่อง
AnyRef.eq(AnyRef)วิธีการเปรียบเทียบเพียงการอ้างอิงที่เป็นที่อินสแตนซ์ตั้งอยู่ในความทรงจำ ไม่มีมวยโดยนัยสำหรับวิธีนี้
1 equals 2จะกลับมาfalseตามที่มันเปลี่ยนเส้นทางไปInteger.equals(...)1 == 2จะกลับมาfalseตามที่มันเปลี่ยนเส้นทางไปInteger.equals(...)1 eq 2 จะไม่คอมไพล์เนื่องจากต้องการอาร์กิวเมนต์ทั้งสองประเภท AnyRefnew ArrayList() equals new ArrayList()จะกลับมาtrueตามที่ตรวจสอบเนื้อหาnew ArrayList() == new ArrayList()จะกลับมาtrueตามที่มันเปลี่ยนเส้นทางไปequals(...)new ArrayList() eq new ArrayList()จะส่งคืนfalseเนื่องจากอาร์กิวเมนต์ทั้งสองเป็นอินสแตนซ์ต่างกันfoo equals fooจะกลับมาtrueเว้นแต่fooจะเป็นnullแล้วจะส่งNullPointerExceptionfoo == fooจะกลับมาtrueแม้ว่าfooจะเป็นnullfoo eq fooจะกลับมาtrueเนื่องจากข้อโต้แย้งทั้งสองเชื่อมโยงไปยังการอ้างอิงเดียวกันมีความแตกต่างที่น่าสนใจระหว่าง==และequalsสำหรับFloatและDoubleประเภท: พวกเขาปฏิบัติNaNแตกต่างกัน:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
แก้ไข:ตามที่ถูกชี้ให้เห็นในความคิดเห็น - "สิ่งนี้ยังเกิดขึ้นใน Java" - ขึ้นอยู่กับสิ่งนี้คือ:
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
สิ่งนี้จะพิมพ์
false
true
true
ดังนั้นunboxedNanอัตราผลตอบแทนfalseเมื่อเทียบกับความเท่าเทียมกันเพราะนี่คือวิธีที่ตัวเลขทศนิยม IEEE กำหนดและสิ่งนี้ควรเกิดขึ้นจริงในทุกภาษาการเขียนโปรแกรม (แม้ว่ามันจะยุ่งกับความคิดของตัวตน)
NaN ชนิดบรรจุกล่องให้ผลจริงสำหรับการเปรียบเทียบโดยใช้ ==ใน Java เนื่องจากเรากำลังเปรียบเทียบการอ้างอิงวัตถุ
ฉันไม่ได้มีคำอธิบายสำหรับequalsกรณี IMHO มันควรจะทำตัวเหมือนกัน==กับค่าสองกล่องที่ไม่ได้ทำ แต่มันไม่มี
สกาลาที่แปลไปยังสกาลานั้นมีความซับซ้อนมากกว่าเล็กน้อยเนื่องจากสกาลามีการรวมกันของวัตถุดั้งเดิมและวัตถุAnyเป็นหนึ่งเดียว ดังนั้นสกาล่า==ชัดเดือดลงไปเปรียบเทียบดั้งเดิมNaNค่า แต่equalsใช้อย่างใดอย่างหนึ่งที่กำหนดไว้ในค่าคู่บรรจุกล่อง (มีเป็นจำนวนมากของเวทมนตร์แปลงนัยที่เกิดขึ้นและมีสิ่ง pimped บนคู่ผสมโดยRichDouble)
หากคุณต้องการตรวจสอบว่ามีการNaNใช้งานจริงหรือไม่isNaN:
ใน Scala ==ก่อนตรวจสอบค่าNullแล้วเรียกใช้ method เท่ากับบนวัตถุแรก