ความแตกต่างระหว่าง==
และ.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
จะไม่คอมไพล์เนื่องจากต้องการอาร์กิวเมนต์ทั้งสองประเภท AnyRef
new ArrayList() equals new ArrayList()
จะกลับมาtrue
ตามที่ตรวจสอบเนื้อหาnew ArrayList() == new ArrayList()
จะกลับมาtrue
ตามที่มันเปลี่ยนเส้นทางไปequals(...)
new ArrayList() eq new ArrayList()
จะส่งคืนfalse
เนื่องจากอาร์กิวเมนต์ทั้งสองเป็นอินสแตนซ์ต่างกันfoo equals foo
จะกลับมาtrue
เว้นแต่foo
จะเป็นnull
แล้วจะส่งNullPointerException
foo == foo
จะกลับมาtrue
แม้ว่าfoo
จะเป็นnull
foo 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 เท่ากับบนวัตถุแรก