วิธีเขียนเท่ากับ () ใน Java
ในตอนท้ายของบทความนี้ ข้อมูลที่จำเป็นทั้งหมดจะครอบคลุมเพื่อให้สามารถเขียนวิธีการเท่ากับ () ที่ดีที่สุดในภาษาการเขียนโปรแกรม Java รายละเอียดของความเท่าเทียมกันจะได้รับการจัดการในแง่ของคำจำกัดความทางคณิตศาสตร์และในลักษณะของภาษาการเขียนโปรแกรม Java เพื่อให้ครอบคลุมข้อมูลพื้นฐานที่จำเป็นในการใช้แนวทางปฏิบัติที่ดีที่สุดของวิธีการเท่ากับ( )
นิยามทางคณิตศาสตร์ของความเท่าเทียมกัน
ตามWikipediaคำจำกัดความของความเท่าเทียมกันทางคณิตศาสตร์คือ
ในวิชาคณิตศาสตร์ ความเท่าเทียมกันคือความสัมพันธ์ระหว่างปริมาณสองปริมาณหรือโดยทั่วไปมากกว่าสองนิพจน์ทางคณิตศาสตร์ โดยยืนยันว่าปริมาณมีค่าเท่ากัน หรือนิพจน์เป็นตัวแทนของวัตถุทางคณิตศาสตร์เดียวกัน ความเท่าเทียมกันระหว่างAและBจะเขียนว่าA = B และออกเสียง ว่า Aเท่ากับB
นิยามของความเท่าเทียมกันในภาษาจาวา
ในภาษาโปรแกรม Java ความเท่าเทียมกันหมายถึงการมีค่าเท่ากัน บางครั้งมีความหมายตามตัวอักษรว่ามีค่าเท่ากันและบางครั้งก็หมายถึงมีโครงสร้างเหมือนกันในแง่ของคุณสมบัติของวัตถุ
เมื่อจำเป็นต้องตรวจสอบความเท่าเทียมกันของค่าประเภทดั้งเดิมสองค่า เครื่องหมายเท่ากับจะถูกใช้โดยตรงตามตัวอย่างด้านล่าง
int a = 5;
int b = 6;
int c = 5;
// Prints "false" since a and b do not have the same value.
System.out.println(a == b);
// Prints "true" since a and c have the same value.
System.out.println(a == c);
ในทางกลับกัน บางครั้งจำเป็นต้องตรวจสอบความเท่าเทียมกันของวัตถุสองชิ้น ในแง่ของวัตถุ มีสองแนวทางที่แตกต่างกันซึ่งใช้ในขั้นตอนต่างๆ ของกระบวนการตรวจสอบความเท่าเทียมกันของวัตถุสองชิ้น มาดูรายละเอียดกัน
ความเท่าเทียมกันในการอ้างอิง
ในภาษาการเขียนโปรแกรม Java ค่าจริงของอ็อบเจกต์จะถูกเก็บไว้ที่ไหนสักแห่งในหน่วยความจำ และค่าเหล่านั้นจะถูกชี้โดยการอ้างอิงอ็อบเจกต์ซึ่งถูกเก็บไว้ที่ไหนสักแห่งในหน่วยความจำด้วย ลองดูตัวอย่างโค้ดต่อไปนี้
// Create an object with "new" operator.
// Point to object with object reference "a".
Object a = new Object();
// Create another object reference.
// Point to the same object as the reference "a" is pointing.
Object b = a;
// Output is true.
System.out.println(a == b);
// Create another object with "new" operator.
// Point to object with object reference "b".
b = new Object();
// Output is false.
System.out.println(a == b);
ในสถานการณ์ดังกล่าว "a" และ "b" เป็นข้อมูลอ้างอิงสองรายการที่ชี้ไปยังวัตถุเดียวกัน ดังนั้นจึงสามารถพูดได้โดยตรงว่า "a" เท่ากับ "b" เนื่องจากได้ค่าความเท่าเทียมกันของการอ้างอิง
อย่างไรก็ตาม สถานการณ์ตรงข้ามไม่ได้ถูกต้องตลอดเวลา การอ้างอิงที่แตกต่างกันสองรายการอาจชี้ตำแหน่งหน่วยความจำต่างกัน แต่วัตถุที่อ้างอิงอาจเท่ากัน
ในชีวิตปกติ บางครั้งก็เปรียบเทียบปริมาณ เช่น ถ้าคุณมีแอปเปิ้ลสองผลและเพื่อนของคุณมีแอปเปิ้ลสองผล จำนวนแอปเปิ้ลที่คุณและเพื่อนมีเท่ากัน
ในทางกลับกัน บางครั้งอาจมีการเปรียบเทียบสิ่งต่าง ๆ ในแง่ของคุณสมบัติหรือโครงสร้างของมันด้วย เรามาดูรายละเอียดสำหรับสถานการณ์นี้กัน
ความเท่าเทียมกันของโครงสร้าง
ความเท่าเทียมกันของโครงสร้างคือประเภทที่เปรียบเทียบวัตถุตามสถานะของคุณสมบัติ จำเป็นต้องใช้เครื่องมือที่ซับซ้อนกว่านี้เพื่อตรวจสอบความเท่าเทียมกันประเภทนี้ แทนที่จะใช้ตัวดำเนินการ "==" เท่านั้น มันเป็นวิธีการเท่ากับ () มันมาจากคลาส Object ซึ่งอยู่ที่จุดสูงสุดของลำดับชั้นของคลาสในภาษาโปรแกรม Java ตรวจสอบข้อมูลโค้ด Java ที่กำลังจะมาถึง
public class Car {
// Assume that we have corresponding constructor, accessors, mutators, etc.
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
}
Car car1 = new Car("Audi","R8", 2023);
Car car2 = new Car("Audi","R8", 2023);
Car car3 = new Car("Audi","R8", 2021);
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
public boolean equals(Object obj) {
return (this == obj);
}
public class Car {
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
// Assume that we have corresponding constructor, accessors, mutators, etc.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
}
ในบรรทัดที่สอง เราเริ่มตรวจสอบตัวตนของวัตถุ หากการอ้างอิงวัตถุoเป็นโมฆะหรือการอ้างอิงวัตถุทั้งสองชี้ไปที่วัตถุที่อยู่ในคลาสที่แตกต่างกัน อาจกล่าวได้โดยตรงว่าวัตถุทั้งสองนี้ไม่มีตัวตนเดียวกันและไม่เท่ากัน หากไม่เป็นเช่นนั้น เราก็สามารถตรวจสอบโครงสร้างที่แท้จริงของวัตถุได้ในที่สุด
ในบรรทัดที่สามของเมธอด เราส่งการอ้างอิงoไปยังประเภทคลาสที่เกี่ยวข้อง เนื่องจากเมธอดถูกแทนที่จากคลาสออบเจกต์ และตอนนี้เรารู้แล้วว่ามันอยู่ในคลาสคาร์
สุดท้าย ในบรรทัดสุดท้ายของวิธีการ โครงสร้างของวัตถุสองชิ้นจะถูกตรวจสอบ และนี่คือบรรทัดจริงที่กำหนดตัวตน พูดง่ายๆ ถ้ารุ่นของแบรนด์และรุ่นปีเหมือนกัน วัตถุทั้งสองนี้ก็มีค่าเท่ากัน นี่คือความเท่าเทียมกันทางโครงสร้าง
เราได้เรียนรู้คุณสมบัติของการเท่ากันทางคณิตศาสตร์ที่โรงเรียนประถมศึกษา คุณสมบัติบางอย่างเหล่านี้ต้องใช้ได้กับ เมธอด เท่ากับ ()ด้วย หมายความว่าต้องเพิ่มคุณสมบัติเหล่านี้ลงในส่วนผสมของวิธีการเท่ากับ () มาดูคุณสมบัติเหล่านี้ในแง่ของความเท่าเทียมกันทางคณิตศาสตร์และในแง่ของความเท่าเทียมกันใน Java
คุณสมบัติสะท้อนแสง
ในนิยามทางคณิตศาสตร์ของสมบัติสะท้อน สำหรับจำนวนจริงทั้งหมดx ;
x = x
จำนวนเท่ากับตัวมันเอง
ในแง่ของความเท่าเทียมกันของ Java วัตถุจะต้องเท่ากับตัวเอง
Car car1 = new Car("Audi","R8",2013);
System.out.println(car1.equals(car1));
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return mileage < car.mileage && brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
คุณสมบัติสมมาตร
ในแง่ของนิยามทางคณิตศาสตร์ของสมบัติสมมาตร สำหรับจำนวนจริงทั้งหมดxและy ;
ถ้าx = yแล้วy = x
ลำดับความเท่าเทียมกันไม่สำคัญ
ในแง่ของความเท่าเทียมกันของ Java ถ้าวัตถุ a เท่ากับวัตถุ b ดังนั้นวัตถุ b จะต้องเท่ากับวัตถุ a;
Car car1 = new Car("Audi","R8",2013);
Car car2 = new Car("Audi","R8",2013);
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car1));
public class Car {
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Car)) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
}
public class SportCar extends Car {
private String engineType;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof SportCar)) return false;
SportCar sportCar = (SportCar) o;
return engineType.equals(sportCar.engineType);
}
}
Car car1 = new Car("Audi", "R8", 2012, 1000);
SportCar car2 = new SportCar("Audi", "R8", 2012, 1000, "4.0");
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car1));
คุณสมบัติสกรรมกริยา
ในนิยามทางคณิตศาสตร์ของคุณสมบัติสกรรมกริยา สำหรับจำนวนจริงทั้งหมดx , yและz ;
ถ้าx = yและy = zแล้วx = z
จำนวนสองจำนวนที่เท่ากับจำนวนเดียวกันมีค่าเท่ากัน
ในแง่ของความเท่าเทียมกันของ Java ถ้าวัตถุ a เท่ากับวัตถุ b และวัตถุ b เท่ากับวัตถุ c ดังนั้นวัตถุ a จะต้องเท่ากับวัตถุ c;
SportCar car1 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("100RPM"));
Car car2 = new Car("Audi", "R8", 2012, 1000);
SportCar car3 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("101RPM"));
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
System.out.println(car1.equals(car3));
public class SportCar extends Car {
private Turbo turbo;
@Override
public boolean equals(Object o) {
if (!(o instanceof Car)) return false;
if (!(o instanceof SportCar)) return o.equals(this);
return super.equals(o) && ((SportCar) o).turbo == turbo;
}
}
public class Turbo {
private String power;
public Turbo(String power) {
this.power = power;
}
}
SportCar car1 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("100RPM"));
Car car2 = new Car("Audi", "R8", 2012, 1000);
SportCar car3 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("101RPM"));
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
System.out.println(car1.equals(car3));
คุณสมบัติที่สอดคล้องกัน
นี่เป็นคุณสมบัติที่แตกต่างกันเนื่องจากไม่มีค่าเทียบเท่าที่แน่นอนทางคณิตศาสตร์ สำหรับสิ่งนี้ เราจำเป็นต้องได้รับผลลัพธ์เดียวกันสำหรับการดำเนินการที่ต่อเนื่องกันของวิธีการเท่ากับ ()
ลองดูข้อมูลโค้ดด้านล่าง
Car car1 = new Car("Audi", "R8", 2012, 1000);
Car car2 = new Car("Audi", "R8", 2012, 1000);
for (int i = 0; i < 100000; i++) {
System.out.println(car1.equals(car2));
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Car)) return false;
Car car = (Car) o;
Random random = new Random();
return brand.equals(car.brand) && model.equals(car.model) && (random.nextInt(10) + 2013) == car.modelYear;
}
หมายเหตุ:ตัวอย่างนี้ไม่ได้ทำให้ฉันพอใจจริงๆ หลังจากการค้นคว้าอย่างถี่ถ้วน ฉันจะแทนที่ด้วยอันที่ดีกว่า มีการกล่าวไว้อย่างชัดเจนในเอกสาร Java ของวิธีการเท่ากับ () ว่า"การเรียกใช้หลายครั้งของx.equals(y)การส่งคืนที่สม่ำเสมอtrueหรือการส่งคืนที่สม่ำเสมอfalse" ต้องมีตัวอย่างที่ชัดเจนของการละเมิดสำหรับข้อความนี้
คุณสมบัติพารามิเตอร์ Null
นี่คือวิธีที่ฉันเลือกเรียกคุณสมบัตินี้
โปรดดูข้อมูลโค้ดด้านล่าง
Car car1 = new Car("Audi", "R8", 2012, 1000);
Car car2 = null;
System.out.println(car1.equals(car2));
ตอนนี้เป็นที่ชัดเจนว่าคุณสมบัติใดที่ควรใช้เมธอดเท่ากับ () เพื่อให้การคำนวณความเท่าเทียมกันถูกต้อง นอกจากนี้ เราได้เห็นสถานการณ์การละเมิดที่เป็นไปได้ ดังนั้นเราจึงสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้เพื่อประโยชน์ของคุณภาพของโค้ดและตรรกะทางธุรกิจ
ปัจจุบัน IDEs จำนวนมากมีกลไกการสร้างเพื่อสร้าง การใช้งานวิธีการเท่ากับ ()ที่ดีที่สุดเท่าที่จะเป็นไปได้ เป็นความคิดที่ดีที่จะอยู่กับพวกเขาเป็นส่วนใหญ่แทนที่จะใช้วิธีเท่ากับ () ลองดูตัวอย่างจากIntellij IDEA ;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear) && mileage.equals(car.mileage);
}
ในบรรทัดแรก มีการตรวจสอบความเท่าเทียมกันของการอ้างอิง เนื่องจากการอ้างอิงวัตถุสองรายการอาจชี้ไปที่วัตถุเดียวกัน
ในบรรทัดที่สอง การตรวจสอบความถูกต้องของNull Parameter Propertyและเช่นเดียวกันกับเงื่อนไข if ที่ทำหน้าที่เป็นguard if clauseโดยการควบคุมประเภทคลาสของออบเจ็กต์ที่ชี้ให้เห็นโดยการอ้างอิง เพื่อป้องกันการละเมิดคุณสมบัติสกรรมกริยาและคุณสมบัติสมมาตร .
ในบรรทัดที่สาม การอ้างอิงออบเจกต์จะถูกส่งไปยังประเภทคลาสที่เกี่ยวข้องซึ่งก็คือ Car ในตัวอย่างของเรา เพื่อเข้าถึงคุณสมบัติของออบเจ็กต์ Car
สุดท้าย ในบรรทัดที่สี่ มีการตรวจสอบความเท่าเทียมกันในแง่ของความเท่าเทียมกันของโครงสร้าง
มีเทมเพลตอื่นสำหรับการสร้างวิธีการเท่ากับ () คุณยังสามารถไปตรวจสอบได้
หากคุณต้องการเขียนการนำไปใช้ด้วยตัวคุณเอง โปรดทราบว่าการนำไปใช้งานต้องรับรองความถูกต้องของคุณสมบัติเมธอดเท่ากับทั้งหมด ()
เมื่อเรามาถึงตอนท้ายของบทความแล้ว ยังมีช่องว่างที่สำคัญมากที่ต้องครอบคลุม เปิด IDE ของคุณและลองสร้างวิธีการเท่ากับ () คุณจะเห็นว่าไม่มีตัวเลือกในการสร้างวิธีเท่ากับ () โดยไม่มี วิธีแฮชโค้ด () เนื่องจากคอลเลกชั่นบางประเภทในภาษาการเขียนโปรแกรม Java จึงเป็นแนวปฏิบัติที่ดีมากที่จะไม่แยกสองวิธีนี้ออกจากกัน มีการกล่าวไว้ในเอกสาร Java อย่างเป็นทางการว่าโดยทั่วไปจำเป็นต้องแทนที่เมธอดhashCode()เมื่อใดก็ตามที่เมธอดเท่ากับ ()ถูกแทนที่ ฉันต้องการให้ข้อมูลที่สอดคล้องกันเกี่ยวกับวิธีการแฮชและแฮชโค้ด ()ในบทความอื่นของฉัน
นอกจากนี้ บางครั้งเราอาจไม่จำเป็นต้องยึดติดกับ คุณสมบัติของเมธอด เท่ากับ ()สำหรับกรณีพิเศษบางอย่าง เช่น คลาสเอนทิตีของ JPA นอกจากนี้ยังสมควรได้รับบทความของตัวเอง
สรุปแล้ว
ประเด็นสำคัญทั้งหมดสำหรับการใช้ วิธี เท่ากับ () ที่ถูก ต้องจะกล่าวถึงในบทความนี้ ฉันยังแนะนำให้คุณเขียนการทดสอบหน่วยที่เกี่ยวข้องเพื่อทดสอบการตรวจสอบคุณสมบัติ ของ เมธอดเท่ากับ () อย่าลืมดูแหล่งข้อมูลอื่น ๆ ที่สามารถพบได้บนเว็บ
ประการแรก ดูเหมือนเป็นหัวข้อที่ง่ายและดั้งเดิมมาก เนื่องจากมาจากพื้นฐานของการออกแบบเชิงวัตถุ อย่างไรก็ตาม ตามที่เห็นจากรายละเอียด สิ่งสำคัญอย่างยิ่งที่จะไม่ข้ามแนวคิดพื้นฐานเหล่านี้และทำความเข้าใจอย่างถ่องแท้





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)