ฝึกฝนการใช้เท่ากับโดยใช้ตัวอย่างต่อไปนี้
package cn.galc.test;public class TestEquals { public static void main(String[] args) { /** * ในที่นี้ วิธีสร้าง Cat() ใช้เพื่อสร้างแมวสองตัวใหม่ในหน่วยความจำฮีป * แมวสองตัว เป็นสี น้ำหนัก และความสูงเหมือนกันทั้งหมด * แต่ c1 และ c2 จะไม่เท่ากัน เนื่องจาก c1 และ c2 เป็นวัตถุอ้างอิงของแมวสองตัวในหน่วยความจำฮีป * มันมีที่อยู่ที่สามารถพบแมวสองตัวได้ แต่เนื่องจากแมวสองตัวถูกเก็บไว้ในช่องว่างที่แตกต่างกันสองแห่งในหน่วยความจำฮีป * c1 และ c2 จึงมีที่อยู่ต่างกัน ดังนั้น c1 และ c2 จะไม่เท่ากัน */ Cat c1 = แมวใหม่ (1, 1, 1); Cat c2 = แมวใหม่ (1, 1, 1); System.out.println("ผลลัพธ์ของ c1==c2 คือ: "+(c1== c2 ));//false System.out.println("ผลลัพธ์ของ c1.equals(c2) คือ: "+c1.equals(c2));//false }}class Cat { int color, น้ำหนัก ส่วนสูง แมวสาธารณะ (int color, int Weight, int height) { this.color = color; this.weight = Weight; this.height = height;วาดแผนภาพการวิเคราะห์หน่วยความจำเพื่อวิเคราะห์ผลการเปรียบเทียบระหว่าง c1 และ c2
โปรแกรม:
Cat c1 = แมวใหม่ (1,1,1); Cat c2 = แมวใหม่ (1,1,1);
หลังจากดำเนินการแล้ว เค้าโครงในหน่วยความจำจะเป็นดังนี้:
c1 ชี้ไปที่วัตถุ และ c2 ยังชี้ไปที่วัตถุ C1 และ c2 มีที่อยู่ที่เก็บไว้ในหน่วยความจำฮีปของวัตถุ Cat ทั้งสองนี้อยู่ในพื้นที่เก็บข้อมูลที่แตกต่างกัน c1 และ c2 มีที่อยู่ของ ไม่เท่ากันอย่างแน่นอน ดังนั้นวัตถุอ้างอิงสองตัว c1 และ c2 จึงไม่เท่ากันอย่างแน่นอน ดังนั้น หากคุณดำเนินการ: "System.out.println(c1==c2);" ผลลัพธ์ที่พิมพ์ออกมาจะเป็นเท็จอย่างแน่นอน ดังนั้นคุณจึงสร้างวัตถุสองชิ้นด้วยวัตถุใหม่ ไม่ต้องกังวล การอ้างอิงของวัตถุทั้งสองจะไม่เหมือนกัน หากวัตถุทั้งสองเหมือนกัน วัตถุหนึ่งจะถูกเขียนทับไม่ได้ ไม่ว่า c1 จะเท่ากับ c2 จะเปรียบเทียบเนื้อหาที่มีอยู่ในการอ้างอิงทั้งสองรายการ c1 และ c2 หรือไม่ เนื่องจากการอ้างอิงของวัตถุทั้งสองที่สร้างโดย new จะไม่เหมือนกัน ดังนั้นเนื้อหาของการอ้างอิงทั้งสองรายการ c1 และ c2 จึงไม่เหมือนกันเช่นกัน c1 ไม่สามารถเท่ากับ c2 ได้ ดังนั้นการเปรียบเทียบการอ้างอิงของวัตถุทั้งสองไม่สามารถทำให้วัตถุทั้งสองเท่ากันหรือเหมือนกันได้
ในการพิจารณาว่าวัตถุทั้งสองเท่ากันหรือไม่ คุณไม่สามารถเปรียบเทียบได้ว่าการอ้างอิงของวัตถุทั้งสองเท่ากันหรือไม่ คุณจะไม่มีทางได้รับผลลัพธ์ที่เท่ากันเนื่องจากการอ้างอิงของวัตถุทั้งสองจะไม่เท่ากัน ดังนั้นวิธีการเปรียบเทียบที่ถูกต้องคือการเปรียบเทียบสิ่งเหล่านี้โดยตรง วัตถุสองชิ้นและเปรียบเทียบว่าสาระสำคัญของวัตถุทั้งสองนั้นเหมือนกันหรือไม่ กล่าวคือ เนื้อหาของวัตถุทั้งสองนั้นเท่ากันหรือไม่ โดยเปรียบเทียบว่าค่าแอตทริบิวต์ของวัตถุทั้งสองนั้นเท่ากันหรือไม่ เหมือนกัน
คลาส Object มีเมธอดเท่ากับ () เพื่อเปรียบเทียบว่าเนื้อหาของทั้งสองอ็อบเจ็กต์เหมือนกันหรือไม่ ดังนั้นเราจึงสามารถใช้วิธีนี้เพื่อเปรียบเทียบว่าทั้งสองอ็อบเจ็กต์มีความ "เท่ากัน" ตามตรรกะหรือไม่ ตัวอย่างเช่น: c1.equals(c2); นี่คือการเรียกเมธอดเท่ากับ() ที่สืบทอดมาจากคลาส Object โดยศึกษาจากเอกสารประกอบ API คำจำกัดความของเมธอดเท่ากับในคลาส Object จะเป็นดังนี้:
บูลีนสาธารณะเท่ากับ (Object obj)
การใช้งานเริ่มต้นของเมธอด Equals() ที่ให้ไว้ในคลาส Object คือการเปรียบเทียบการอ้างอิงของวัตถุปัจจุบันกับการอ้างอิงที่คุณต้องการเปรียบเทียบเพื่อดูว่าพวกมันชี้ไปที่วัตถุเดียวกันหรือไม่ ซึ่งเหมือนกับ "c1==c2 ". , "c1.equals(c2)" และ "c1==c2" เทียบเท่ากันโดยสิ้นเชิง ดังนั้นการใช้เมธอดเท่ากับ() ที่สืบทอดมาโดยตรงจึงไม่สามารถเปรียบเทียบได้โดยตรงว่าเนื้อหาของทั้งสองอ็อบเจ็กต์เหมือนกันหรือไม่ ด้วยเหตุนี้ เราจึงต้องแทนที่เมธอดเท่ากับ() และเปลี่ยนการใช้งานเริ่มต้นของเมธอดนี้
จากนั้นให้เขียนวิธีการเท่ากับ () ที่สืบทอดมาในคลาส Cat:
class Cat { int color, น้ำหนัก, ส่วนสูง; public Cat(int color, int weight, int height) { this.color = color; this.weight = Weight; this.height = height; เมธอดเท่ากับ() ที่สืบทอดมาจากคลาส Object จะเปลี่ยนการใช้งานเริ่มต้นของเมธอดนี้ * ในที่นี้เราให้คำนิยามว่าถ้าสี น้ำหนัก และส่วนสูงของแมวสองตัวเท่ากัน * แล้วเราคิดว่าแมวสองตัวมีเหตุผลเหมือนกัน นั่นคือ แมวสองตัว "เท่ากัน" */ บูลีนสาธารณะเท่ากับ(Object obj){ if (obj==null){ return false; } else{ /** * instanceof เป็นตัวดำเนินการอ็อบเจ็กต์ * ตัวดำเนินการวัตถุใช้เพื่อตรวจสอบว่าวัตถุเป็นของอินสแตนซ์ของคลาสที่ระบุหรือคลาสย่อยที่ระบุ * ตัวดำเนินการอ็อบเจ็กต์เป็นคำรวมของ instanceof * ตัวดำเนินการนี้เป็นตัวดำเนินการไบนารี นิพจน์ทางด้านซ้ายเป็นวัตถุและนิพจน์ทางด้านขวาคือคลาส * หากวัตถุทางด้านซ้ายเป็นวัตถุที่สร้างโดยคลาสทางด้านขวา ผลลัพธ์ของการดำเนินการคือ จริง ไม่เช่นนั้นจะเป็นเท็จ */ if (obj instanceof Cat){ Cat c = (Cat)obj; if (c.color==this.color && c.weight==this.weight && c.height==this.height){ กลับจริง; } } } กลับเท็จ; }} ในขณะนี้ ให้ดำเนินการคำสั่งการพิมพ์ด้วยวิธีการหลัก:
public static void main(String[] args) { /** * ในที่นี้ วิธีสร้าง Cat() ใช้เพื่อสร้างแมวสองตัวใหม่ในหน่วยความจำฮีป * สี น้ำหนัก และความสูงของแมวสองตัวนี้เหมือนกัน . * แต่ c1 และ c2 จะไม่เท่ากัน เนื่องจาก c1 และ c2 เป็นวัตถุอ้างอิงของแมวสองตัวในหน่วยความจำฮีป * มีที่อยู่ที่สามารถพบแมวสองตัวได้ แต่เนื่องจากแมวสองตัวถูกเก็บไว้ใน หน่วยความจำฮีปในสองช่องว่างที่แตกต่างกัน * ดังนั้น c1 และ c2 มีที่อยู่ต่างกัน ดังนั้น c1 และ c2 จะไม่เท่ากัน */ Cat c1 = แมวใหม่ (1, 1, 1); Cat c2 = แมวใหม่ (1, 1, 1); System.out.println("ผลลัพธ์ของ c1==c2 คือ: "+(c1== c2 ));//false System.out.println("ผลลัพธ์ของ c1.equals(c2) คือ: "+c1.equals(c2));//true }ผลลัพธ์ที่ได้รับในครั้งนี้แตกต่างจากผลลัพธ์ที่ได้รับครั้งล่าสุดโดยไม่ต้องแทนที่เมธอดเท่ากับ ():
"System.out.println(c1 == c2);" ผลลัพธ์ที่พิมพ์ออกมายังคงเป็นเท็จ เนื่องจากมีการเปรียบเทียบเนื้อหาของการอ้างอิงทั้งสองนั้นแน่นอนว่าจะไม่เท่ากัน เท่ากัน ดังนั้นผลลัพธ์ที่พิมพ์ออกมาต้องเป็นเท็จ
"System.out.println(c1.equals(c2));" ผลลัพธ์ที่พิมพ์ออกมาเป็นจริง เนื่องจากเราได้เขียนเมธอดเท่ากับ() ในคลาส Cat และเปลี่ยนการใช้งานเริ่มต้นของเมธอดนี้ วิธีการเปลี่ยนเป็นเท่านั้น หากวัตถุทั้งสองนี้มีอยู่จริงและเป็นแมวทั้งคู่ และมีสี ส่วนสูง และน้ำหนักเท่ากัน แสดงว่าแมวทั้งสองมีตรรกะที่เหมือนกันและเหมือนกันทุกประการ กล่าวคือ แมวสองตัวนี้ "เท่ากัน" ผลลัพธ์ที่พิมพ์ไว้ที่นี่จึงเป็นจริง
แล้วจะเปรียบเทียบวัตถุสตริงสองตัวเพื่อความเท่าเทียมกันได้อย่างไร
ดูตัวอย่างต่อไปนี้:
TestEquals คลาสสาธารณะ { โมฆะสาธารณะหลัก (String args []) { String s1 = new String ("hello"); String s2 = new String ("hello"); System.out.println ("s1 == s2 ผลลัพธ์คือ : "+(s1 == s2));//false System.out.println("ผลลัพธ์ของ s1.equals(s2) คือ: "+s1.equals(s2));//true }}คราวนี้วัตถุสตริงทั้งสองถูกเปรียบเทียบเพื่อความเท่าเทียมกัน:
System.out.println(s1 == s2);
ผลลัพธ์ที่พิมพ์ยังคงเป็นเท็จ เนื่องจากมีการเปรียบเทียบการอ้างอิงของวัตถุสตริงทั้งสอง s1 และ s2 ที่นี่ การอ้างอิงของวัตถุทั้งสองจะไม่เท่ากัน ดังนั้นผลลัพธ์ที่พิมพ์ออกมาจึงเป็นเท็จ
System.out.println(s1.เท่ากับ(s2));
ผลลัพธ์ที่พิมพ์ออกมานั้นเป็นจริง เนื่องจากการสืบทอดจากคลาส Object จะถูกเขียนใหม่ในคลาส String (คลาสทั้งหมดสืบทอดมาจากคลาส Object และแน่นอนว่าคลาส String ก็ไม่มีข้อยกเว้น หากคุณสืบทอดจากคลาสพาเรนต์ คุณจะมีทุกอย่าง ของคลาสพาเรนต์ คุณสมบัติและวิธีการ ดังนั้นคลาส Sting จึงมีเมธอดเท่ากับ () และเมธอดเท่ากับ () ที่สืบทอดมาก็ถูกเขียนใหม่ด้วย) โดยเปลี่ยนการใช้งานเริ่มต้นของเมธอดนี้
ในคลาส String การใช้งานเมธอดเท่ากับ () จะถูกแทนที่ดังนี้: เปรียบเทียบวัตถุสตริงปัจจุบันกับวัตถุสตริงที่ระบุ ต้องไม่ว่างเปล่า และลำดับอักขระของวัตถุนี้เหมือนกับสตริงปัจจุบัน ลำดับสตริงของออบเจ็กต์จะเหมือนกัน หากตรงตามเงื่อนไขเหล่านี้ ออบเจ็กต์สตริงทั้งสองจะเท่ากัน
ดังนั้น s2 ที่นี่ตรงตามเงื่อนไข ดังนั้นผลลัพธ์ที่พิมพ์ออกมาจึงเป็นจริง
ในอนาคต เมื่อเปรียบเทียบสองอ็อบเจ็กต์ในคลาสหนึ่งเพื่อความเท่าเทียมกัน ก่อนอื่นให้ไปที่เอกสารประกอบ API เพื่อดูว่าคลาสนี้ได้แทนที่เมธอดเท่ากับ () ที่สืบทอดมาจากคลาสอ็อบเจ็กต์หรือไม่ หากเมธอดเท่ากับ() ถูกแทนที่ เมธอดที่ถูกแทนที่จะถูกเรียกเมื่อเปรียบเทียบว่าทั้งสองอ็อบเจ็กต์เท่ากันหรือไม่ หากไม่ได้ถูกแทนที่ เมธอดที่สืบทอดมาจากคลาส Object จะถูกเรียกโดยตรงว่าเมธอดเท่ากับ() ใช้วิธีการเริ่มต้นของเท่ากับ () เพื่อเปรียบเทียบว่าวัตถุทั้งสองเท่ากันหรือไม่ ดังนั้นแต่ละคลาสจึงสามารถแทนที่เมธอดเท่ากับ () ที่สืบทอดมาจากคลาส Object ได้ตามต้องการ
สำหรับการค้นหาคลาสใดคลาสหนึ่งในเอกสาร API หากคลาสนั้นสามารถใช้ได้โดยตรงโดยไม่ต้องแนะนำแพ็คเกจ คลาสนี้จะต้องอยู่ในแพ็คเกจ java.lang ตัวอย่างเช่น คลาส String ที่นี่สามารถใช้ได้โดยตรง ดังนั้นคลาส String จะต้องอยู่ในแพ็คเกจ java.lang เมื่อใช้คลาสใดคลาสหนึ่ง ให้ตรวจสอบว่าคลาสใดนำเข้ามา จากนั้นไปที่แพ็คเกจเพื่อค้นหาคลาสที่ไม่จำเป็นต้องนำเข้าแพ็คเกจจะต้องอยู่ใน java.lang เพียงไปที่ java.lang โดยตรงเพื่อค้นหาคลาสนั้น .
โดยทั่วไป เมื่อเราออกแบบคลาส เราจำเป็นต้องแทนที่เมธอดเท่ากับของคลาสพาเรนต์ เมื่อเขียนเมธอดนี้ใหม่ เราจำเป็นต้องออกแบบตามกฎต่อไปนี้:
1. การสะท้อนกลับ: สำหรับค่าอ้างอิง X ค่าที่ส่งกลับของ x.equals(x) จะต้องเป็นจริง
2. สมมาตร: สำหรับค่าอ้างอิงใดๆ x, y หากค่าที่ส่งกลับของ y.equals(x) เป็นจริง ค่าที่ส่งกลับของ x.equals(y) จะต้องเป็นจริง
3. การผ่านผ่าน: ถ้า x.equals(y)=true, y.equals(z)=true แล้ว x.equals(z)=true
4. ความสม่ำเสมอ: หากวัตถุที่เข้าร่วมในการเปรียบเทียบไม่เปลี่ยนแปลง ผลลัพธ์ของการเปรียบเทียบวัตถุก็ไม่ควรเปลี่ยนแปลงเช่นกัน
5. ความไม่มีค่าเป็นโมฆะ: สำหรับค่าอ้างอิง X ที่ไม่ใช่ค่าว่าง ค่าที่ส่งกลับของ x.equals(null) ต้องเป็นเท็จ
ตัวอย่างเช่น:
คลาสสาธารณะ { firstName สตริงส่วนตัว; สตริงสาธารณะ getFirstName () { กลับนามสกุล; } โมฆะสาธารณะ setLastName (นามสกุลสตริง) { this.lastName = นามสกุล; } สาธารณะ int getAge() { คืนอายุ; } โมฆะสาธารณะ setAge (int อายุ) this.age = age; } @Override บูลีนสาธารณะเท่ากับ (Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; People other = (คน) obj; if (อายุ != other.age) กลับ false; if (firstName == null) { if (other.firstName != null) ส่งคืน false; (!firstName.equals(other.firstName)) ส่งคืนเท็จ if (lastName == null) { if (other.lastName != null) ส่งคืน false; } else if (!lastName.equals(other.lastName)) ส่งคืนเท็จ ; กลับเป็นจริง; }}
ในตัวอย่างนี้ เรากำหนดว่าบุคคลคือบุคคลเดียวกันหากนามสกุล ชื่อ และอายุเหมือนกัน แน่นอน คุณสามารถเพิ่มคุณลักษณะอื่นๆ ได้ เช่น หมายเลข ID จะต้องเหมือนกันจึงจะตัดสินเป็นคนคนเดียวกันได้ จากนั้นจึงเพิ่มการตัดสินหมายเลข ID ด้วยวิธีเท่ากับได้
สรุป: เพื่อเปรียบเทียบว่าวัตถุสองชิ้นเท่ากันหรือไม่ เราใช้วิธีเท่ากับ() เรากำหนดเงื่อนไขในการตัดสินว่าวัตถุสองชิ้นเท่ากันหรือไม่หลังจากเขียนการใช้วิธีเท่ากับ() ใหม่ เพื่อให้วิธีเท่ากับ() สามารถ ใช้งานได้ยืดหยุ่นมากขึ้น เปรียบเทียบวัตถุสองชิ้นในคลาสเดียวกันในคลาสที่แตกต่างกันเพื่อดูว่าเท่ากันหรือไม่