JavaRush /จาวาบล็อก /Random-TH /การเปรียบเทียบวัตถุ: การปฏิบัติ
articles
ระดับ

การเปรียบเทียบวัตถุ: การปฏิบัติ

เผยแพร่ในกลุ่ม
นี่เป็นบทความที่สองเกี่ยวกับการเปรียบเทียบวัตถุ คนแรกพูดคุยเกี่ยวกับพื้นฐานทางทฤษฎีของการเปรียบเทียบ - ทำอย่างไรทำไมจึงใช้ที่ไหน ในบทความนี้ เราจะพูดถึงการเปรียบเทียบตัวเลข วัตถุ กรณีพิเศษ รายละเอียดปลีกย่อย และจุดที่ไม่เห็นชัดเจน ต่อไปนี้คือสิ่งที่เราจะพูดถึง:
การเปรียบเทียบวัตถุ: แบบฝึกหัด - 1
  • การเปรียบเทียบสตริง: ' ==' และequals
  • วิธีString.intern
  • การเปรียบเทียบดั้งเดิมที่แท้จริง
  • +0.0และ-0.0
  • ความหมายNaN
  • จาวา 5.0 การสร้างวิธีการและการเปรียบเทียบผ่าน ' =='
  • จาวา 5.0 การทำกล่องอัตโนมัติ/แกะกล่อง: ' ==', ' >=' และ ' <=' สำหรับการตัดคำอ็อบเจ็กต์
  • จาวา 5.0 การเปรียบเทียบองค์ประกอบ enum (ประเภทenum)
มาเริ่มกันเลย!

การเปรียบเทียบสตริง: ' ==' และequals

เอ่อ เส้นพวกนี้... เป็นประเภทที่ใช้บ่อยที่สุดชนิดหนึ่งซึ่งทำให้เกิดปัญหามากมาย โดยหลักการแล้ว มีบทความแยกต่างหาก เกี่ยวกับพวก เขา และที่นี่ฉันจะพูดถึงประเด็นการเปรียบเทียบ แน่นอนว่าสามารถเปรียบเทียบสตริงได้โดยใช้equals. ยิ่งไปกว่านั้น จะต้องเปรียบเทียบผ่านequals. อย่างไรก็ตามยังมีรายละเอียดปลีกย่อยที่ควรค่าแก่การรู้ ประการแรก สตริงที่เหมือนกันจริงๆ แล้วเป็นออบเจ็กต์เดียว สามารถตรวจสอบได้อย่างง่ายดายโดยใช้รหัสต่อไปนี้:
String str1 = "string";
String str2 = "string";
System.out.println(str1==str2 ? "the same" : "not the same");
ผลลัพธ์ก็จะ"เหมือนเดิม" . ซึ่งหมายความว่าการอ้างอิงสตริงมีค่าเท่ากัน ซึ่งทำได้ในระดับคอมไพเลอร์ เพื่อประหยัดหน่วยความจำอย่างเห็นได้ชัด คอมไพเลอร์สร้างหนึ่งอินสแตนซ์ของสตริง และกำหนดการstr1อ้างอิงstr2ให้กับอินสแตนซ์นี้ อย่างไรก็ตาม สิ่งนี้ใช้ได้กับสตริงที่ประกาศเป็นตัวอักษรในโค้ดเท่านั้น หากคุณเขียนสตริงจากชิ้นส่วนต่างๆ ลิงก์ไปยังสตริงนั้นจะแตกต่างออกไป การยืนยัน - ตัวอย่างนี้:
String str1 = "string";
String str2 = "str";
String str3 = "ing";
System.out.println(str1==(str2+str3) ? "the same" : "not the same");
ผลลัพธ์จะ“ไม่เหมือนเดิม ” คุณยังสามารถสร้างวัตถุใหม่โดยใช้ตัวสร้างการคัดลอก:
String str1 = "string";
String str2 = new String("string");
System.out.println(str1==str2 ? "the same" : "not the same");
ผลลัพธ์ก็จะ“ไม่เหมือนเดิม” เช่นกัน ดังนั้นบางครั้งจึงสามารถเปรียบเทียบสตริงผ่านการเปรียบเทียบอ้างอิงได้ แต่อย่าพึ่งสิ่งนี้ดีกว่า ฉันอยากจะพูดถึงวิธีการหนึ่งที่น่าสนใจมากที่ช่วยให้คุณได้รับสิ่งที่เรียกว่าการแสดงสตริงตามรูปแบบบัญญัติString.intern- มาพูดถึงรายละเอียดเพิ่มเติมกันดีกว่า

วิธีการ String.intern

เริ่มจากความจริงที่ว่าคลาสStringรองรับพูลสตริง ตัวอักษรสตริงทั้งหมดที่กำหนดไว้ในคลาส ไม่เพียงแต่จะถูกเพิ่มลงในพูลนี้ ดังนั้นเมธอดนี้internช่วยให้คุณได้รับสตริงจากพูลนี้ซึ่งเท่ากับอันที่มีอยู่ (อันที่เรียกใช้เมธอดintern) จากมุมมองequalsของ หากไม่มีแถวดังกล่าวอยู่ในพูล แถวที่มีอยู่จะถูกวางไว้ตรงนั้นและลิงก์ไปยังแถวนั้นจะถูกส่งกลับ ดังนั้น แม้ว่าการอ้างอิงถึงสองสตริงที่เท่ากันจะแตกต่างกัน (ดังในสองตัวอย่างข้างต้น) การเรียกสตริงเหล่านี้internจะส่งคืนการอ้างอิงไปยังออบเจ็กต์เดียวกัน:
String str1 = "string";
String str2 = new String("string");
System.out.println(str1.intern()==str2.intern() ? "the same" : "not the same");
ผลลัพธ์ของการรันโค้ดชิ้นนี้จะเป็น"เหมือนกัน " ฉันไม่สามารถพูดได้อย่างชัดเจนว่าเหตุใดจึงทำเช่นนี้ วิธีการนี้internเป็นวิธีการดั้งเดิม และบอกตามตรงว่าฉันไม่ต้องการเข้าไปในโค้ด C แบบไวด์ เป็นไปได้มากว่าสิ่งนี้เกิดขึ้นเพื่อปรับการใช้หน่วยความจำและประสิทธิภาพให้เหมาะสม ไม่ว่าในกรณีใด คุณควรทราบเกี่ยวกับคุณลักษณะการใช้งานนี้ เรามาดูส่วนต่อไปกันดีกว่า

การเปรียบเทียบดั้งเดิมที่แท้จริง

เริ่มต้นด้วยฉันต้องการถามคำถาม ง่ายมาก. ผลรวมต่อไปนี้ – 0.3f + 0.4f คืออะไร? ทำไม 0.7f? มาตรวจสอบกัน:
float f1 = 0.7f;
float f2 = 0.3f + 0.4f;
System.out.println("f1==f2: "+(f1==f2));
ผลที่ตามมา? ชอบ? ฉันด้วย. ส่วนใครที่ยังทำไม่ครบแฟรกเมนต์นี้บอกเลยว่าผลลัพธ์ที่ได้คือ...
f1==f2: false
เหตุใดสิ่งนี้จึงเกิดขึ้น?.. เรามาทำการทดสอบอีกครั้ง:
float f1 = 0.3f;
float f2 = 0.4f;
float f3 = f1 + f2;
float f4 = 0.7f;
System.out.println("f1="+(double)f1);
System.out.println("f2="+(double)f2);
System.out.println("f3="+(double)f3);
System.out.println("f4="+(double)f4);
สังเกตการแปลงเป็นdouble. ทำเช่นนี้เพื่อให้แสดงตำแหน่งทศนิยมมากขึ้น ผลลัพธ์:
f1=0.30000001192092896
f2=0.4000000059604645
f3=0.7000000476837158
f4=0.699999988079071
พูดอย่างเคร่งครัดผลลัพธ์สามารถคาดเดาได้ การแทนเศษส่วนจะดำเนินการโดยใช้อนุกรมจำกัด 2-n ดังนั้นจึงไม่จำเป็นต้องพูดถึงการแทนค่าที่แน่นอนของจำนวนที่เลือกโดยพลการ จากตัวอย่างจะเห็นได้ว่าความแม่นยำในการนำเสนอfloatคือทศนิยม 7 ตำแหน่ง พูดอย่างเคร่งครัด การแสดงfloat จะจัดสรร 24 บิตให้กับแมนทิสซา ดังนั้น จำนวนสัมบูรณ์ขั้นต่ำที่สามารถแสดงได้โดยใช้ float (โดยไม่คำนึงถึงระดับเนื่องจากเรากำลังพูดถึงความแม่นยำ) คือ 2-24µ6*10-8 ด้วยขั้นตอนนี้ค่าต่างๆ ในการเป็นตัวแทนจะไปได้ floatจริง และเนื่องจากมีการหาปริมาณ จึงมีข้อผิดพลาดด้วย ดังนั้นข้อสรุป: ตัวเลขในการเป็นตัวแทนfloatสามารถเปรียบเทียบได้ด้วยความแม่นยำที่แน่นอนเท่านั้น ฉันขอแนะนำให้ปัดเศษให้เป็นทศนิยมตำแหน่งที่ 6 (10-6) หรือควรตรวจสอบค่าสัมบูรณ์ของความแตกต่างระหว่างกัน:
float f1 = 0.3f;
float f2 = 0.4f;
float f3 = f1 + f2;
float f4 = 0.7f;
System.out.println("|f3-f4|<1e-6: "+( Math.abs(f3-f4) < 1e-6 ));
ในกรณีนี้ ผลลัพธ์ที่ได้คือกำลังใจ:
|f3-f4|<1e-6: true
แน่นอนว่ารูปภาพนั้นเหมือนกันทุกประการกับdoubleประเภท ข้อแตกต่างเพียงอย่างเดียวคือมีการจัดสรร 53 บิตสำหรับแมนทิสซา ดังนั้นความแม่นยำในการนำเสนอคือ 2-53µ10-16 ใช่ ค่าเชิงปริมาณน้อยกว่ามากแต่ก็ยังคงอยู่ และมันสามารถเล่นตลกที่โหดร้ายได้ อย่างไรก็ตาม ใน ไลบรารีทดสอบ JUnitในวิธีการเปรียบเทียบจำนวนจริง ความแม่นยำจะถูกระบุอย่างชัดเจน เหล่านั้น. วิธีการเปรียบเทียบประกอบด้วยพารามิเตอร์สามตัว ได้แก่ ตัวเลข สิ่งที่ควรเท่ากับ และความแม่นยำของการเปรียบเทียบ อย่างไรก็ตาม ฉันอยากจะพูดถึงรายละเอียดปลีกย่อยที่เกี่ยวข้องกับการเขียนตัวเลขในรูปแบบวิทยาศาสตร์เพื่อระบุระดับ คำถาม. จะเขียน 10-6 ได้อย่างไร? การปฏิบัติแสดงให้เห็นว่ามากกว่า 80% คำตอบ – 10e-6 ในขณะเดียวกันคำตอบที่ถูกต้องคือ 1e-6! และ 10e-6 คือ 10-5! เราเหยียบคราดนี้ในโครงการใดโครงการหนึ่งโดยไม่คาดคิด พวกเขามองหาข้อผิดพลาดเป็นเวลานานดูค่าคงที่ 20 ครั้ง และไม่มีใครมีข้อสงสัยเกี่ยวกับความถูกต้องของพวกเขาจนกระทั่งวันหนึ่งโดยบังเอิญส่วนใหญ่มีการพิมพ์ค่าคงที่ 10e-3 และพวกเขาพบสองรายการ หลักหลังจุดทศนิยมแทนที่จะเป็นสามหลัก ดังนั้นควรระวัง! เดินหน้าต่อไป

+0.0 และ -0.0

ในการแทนจำนวนจริง บิตที่สำคัญที่สุดจะถูกเซ็นชื่อ จะเกิดอะไรขึ้นถ้าบิตอื่นๆ ทั้งหมดเป็น 0? ต่างจากจำนวนเต็ม ซึ่งในสถานการณ์เช่นนี้ ผลลัพธ์จะเป็นจำนวนลบซึ่งอยู่ที่ขีดจำกัดล่างของช่วงการแทนค่า จำนวนจริงที่มีเพียงบิตที่มีนัยสำคัญที่สุดซึ่งตั้งค่าเป็น 1 ก็หมายถึง 0 เช่นกัน โดยมีเครื่องหมายลบเท่านั้น ดังนั้นเราจึงมีศูนย์สองตัว - +0.0 และ -0.0 มีคำถามเชิงตรรกะเกิดขึ้น: ตัวเลขเหล่านี้ควรถือว่าเท่ากันหรือไม่? เครื่องเสมือนคิดแบบนี้อย่างแน่นอน อย่างไรก็ตาม ตัวเลขเหล่านี้เป็น ตัวเลข ที่แตกต่างกัน สองตัว เนื่องจากผลการดำเนินการกับตัวเลขเหล่านี้ ทำให้ได้ค่าที่ต่างกัน:
float f1 = 0.0f/1.0f;
float f2 = 0.0f/-1.0f;
System.out.println("f1="+f1);
System.out.println("f2="+f2);
System.out.println("f1==f2: "+(f1==f2));
float f3 = 1.0f / f1;
float f4 = 1.0f / f2;
System.out.println("f3="+f3);
System.out.println("f4="+f4);
... และผลลัพธ์:
f1=0.0
f2=-0.0
f1==f2: true
f3=Infinity
f4=-Infinity
ดังนั้นในบางกรณี จึงสมเหตุสมผลที่จะถือว่า +0.0 และ -0.0 เป็นตัวเลขสองตัวที่ต่างกัน และถ้าเรามีวัตถุสองชิ้น โดยอันหนึ่งมีฟิลด์ +0.0 และอีกอันคือ -0.0 วัตถุเหล่านี้ก็ถือว่าไม่เท่ากันได้เช่นกัน คำถามเกิดขึ้น - คุณจะเข้าใจได้อย่างไรว่าตัวเลขไม่เท่ากันหากการเปรียบเทียบโดยตรงกับเครื่องเสมือนให้true? คำตอบคือสิ่งนี้ แม้ว่าเครื่องเสมือนจะถือว่าตัวเลขเหล่านี้เท่ากัน แต่การแสดงก็ยังคงแตกต่างกัน ดังนั้นสิ่งเดียวที่ทำได้คือการเปรียบเทียบมุมมอง และเพื่อให้ได้มา มีวิธีการint Float.floatToIntBits(float)และlong Double.doubleToLongBits(double)ซึ่งส่งคืนการแสดงบิตในรูปแบบintและlongตามลำดับ (ต่อจากตัวอย่างก่อนหน้า):
int i1 = Float.floatToIntBits(f1);
int i2 = Float.floatToIntBits(f2);
System.out.println("i1 (+0.0):"+ Integer.toBinaryString(i1));
System.out.println("i2 (-0.0):"+ Integer.toBinaryString(i2));
System.out.println("i1==i2: "+(i1 == i2));
ผลลัพธ์ที่ได้ก็จะเป็น
i1 (+0.0):0
i2 (-0.0):10000000000000000000000000000000
i1==i2: false
ดังนั้น หากคุณมี +0.0 และ -0.0 เป็นตัวเลขที่แตกต่างกัน คุณควรเปรียบเทียบตัวแปรจริงผ่านการแสดงบิตของตัวแปรเหล่านั้น ดูเหมือนว่าเราจะแยกแยะ +0.0 และ -0.0 ได้แล้ว อย่างไรก็ตาม -0.0 ไม่ใช่สิ่งเดียวที่น่าประหลาดใจ ยังมีเรื่องเช่น...

ค่าน่าน

NaNหมายถึงNot-a-Number. ค่านี้ปรากฏเป็นผลมาจากการคำนวณทางคณิตศาสตร์ที่ไม่ถูกต้อง เช่น หาร 0.0 ด้วย 0.0 อนันต์ด้วยอนันต์ เป็นต้น ลักษณะเฉพาะของค่านี้คือมันไม่เท่ากับตัวมันเอง เหล่านั้น.:
float x = 0.0f/0.0f;
System.out.println("x="+x);
System.out.println("x==x: "+(x==x));
...จะส่งผลให้...
x=NaN
x==x: false
สิ่งนี้จะเกิดขึ้นได้อย่างไรเมื่อเปรียบเทียบวัตถุ? หากสนามของวัตถุเท่ากับNaNดังนั้นการเปรียบเทียบจะให้falseเช่น วัตถุรับประกันว่าจะถือว่าไม่เท่ากัน แม้ว่าตามตรรกะแล้ว เราอาจต้องการสิ่งที่ตรงกันข้ามก็ตาม คุณสามารถบรรลุผลลัพธ์ที่ต้องการได้โดยใช้วิธีFloat.isNaN(float)การ จะส่งกลับtrueถ้าอาร์กิวเมนต์NaNเป็น ในกรณีนี้ ฉันจะไม่พึ่งพาการเปรียบเทียบการแสดงบิต เพราะ มันไม่ได้มาตรฐาน บางทีนั่นอาจเพียงพอแล้วเกี่ยวกับเรื่องดั้งเดิม ตอนนี้เรามาดูรายละเอียดปลีกย่อยที่ปรากฏใน Java ตั้งแต่เวอร์ชัน 5.0 กันดีกว่า และประเด็นแรกที่ผมอยากพูดถึงก็คือ

จาวา 5.0 การสร้างวิธีการและการเปรียบเทียบผ่าน ' =='

มีรูปแบบในการออกแบบที่เรียกว่าวิธีการผลิต. บางครั้งการใช้งานก็ให้ผลกำไรมากกว่าการใช้คอนสตรัคเตอร์มาก ผมขอยกตัวอย่างให้คุณฟัง ฉันคิดว่าฉันรู้จักวัตถุเชลล์Booleanดี คลาสนี้ไม่เปลี่ยนรูปและสามารถมีเพียงสองค่าเท่านั้น นั่นคือในความเป็นจริงสำหรับความต้องการใด ๆ เพียงสองชุดก็เพียงพอแล้ว และถ้าคุณสร้างมันไว้ล่วงหน้าแล้วส่งคืน มันจะเร็วกว่าการใช้คอนสตรัคเตอร์มาก มี วิธีดังกล่าวBoolean: valueOf(boolean). ปรากฏในเวอร์ชัน 1.4 วิธีการผลิตที่คล้ายกันถูกนำมาใช้ในเวอร์ชัน 5.0 ในคลาสByte, Character, Shortและ เมื่อคลาสเหล่านี้ถูกโหลด อาร์เรย์ของอินสแตนซ์จะถูกสร้างขึ้นโดยสอดคล้องกับช่วงของค่าดั้งเดิมบางช่วง ช่วงเหล่านี้มีดังนี้: IntegerLong
การเปรียบเทียบวัตถุ: แบบฝึกหัด - 2
ซึ่งหมายความว่าเมื่อใช้เมธอดนี้valueOf(...)หากอาร์กิวเมนต์อยู่ในช่วงที่ระบุ ออบเจ็กต์เดียวกันก็จะถูกส่งกลับเสมอ บางทีนี่อาจช่วยเพิ่มความเร็วได้บ้าง แต่ในขณะเดียวกันปัญหาก็เกิดขึ้นในลักษณะที่อาจเป็นเรื่องยากมากที่จะไปถึงจุดต่ำสุด อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ ตามทฤษฎีแล้ว วิธีการผลิตได้valueOfถูกเพิ่มให้กับทั้ง คลาส Floatและ Doubleคำอธิบายของพวกเขาบอกว่าหากคุณไม่ต้องการสำเนาใหม่ ก็ควรใช้วิธีนี้ดีกว่าเพราะว่า มันสามารถเพิ่มความเร็วได้ ฯลฯ และอื่น ๆ อย่างไรก็ตามในการใช้งานปัจจุบัน (Java 5.0) อินสแตนซ์ใหม่จะถูกสร้างขึ้นในวิธีนี้ กล่าวคือ ไม่รับประกันการใช้งานเพื่อเพิ่มความเร็ว ยิ่งไปกว่านั้น มันเป็นเรื่องยากสำหรับฉันที่จะจินตนาการว่าวิธีนี้สามารถเร่งความเร็วได้อย่างไร เนื่องจากเนื่องจากความต่อเนื่องของค่า จึงไม่สามารถจัดระเบียบแคชที่นั่นได้ ยกเว้นจำนวนเต็ม ฉันหมายถึงไม่มีเศษส่วน

จาวา 5.0 การทำกล่องอัตโนมัติ/แกะกล่อง: ' ==', ' >=' และ ' <=' สำหรับการตัดคำอ็อบเจ็กต์

ฉันสงสัยว่าวิธีการผลิตและแคชอินสแตนซ์ถูกเพิ่มลงใน wrapper สำหรับจำนวนเต็มดั้งเดิมเพื่อปรับการดำเนินงานให้autoboxing/unboxingเหมาะสม ฉันขอเตือนคุณว่ามันคืออะไร หากออบเจ็กต์ต้องเกี่ยวข้องกับการดำเนินการ แต่มี primitive เข้ามาเกี่ยวข้อง ดังนั้น primitive นี้จะถูกรวมไว้ใน wrapper อ็อบเจ็กต์โดยอัตโนมัติ นี้autoboxing. และในทางกลับกัน - หากต้องเกี่ยวข้องกับการดำเนินการแบบดั้งเดิม คุณสามารถแทนที่เชลล์อ็อบเจ็กต์ที่นั่นได้ และค่าจะถูกขยายจากเชลล์นั้นโดยอัตโนมัติ นี้unboxing. โดยปกติแล้วคุณต้องจ่ายเงินเพื่อความสะดวกสบายดังกล่าว การดำเนินการแปลงอัตโนมัติทำให้แอปพลิเคชันช้าลงบ้าง อย่างไรก็ตาม สิ่งนี้ไม่เกี่ยวข้องกับหัวข้อปัจจุบัน ดังนั้นจึงขอทิ้งคำถามนี้ไว้ ทุกอย่างเรียบร้อยดีตราบใดที่เราจัดการกับการดำเนินการที่เกี่ยวข้องกับดั้งเดิมหรือเชลล์อย่างชัดเจน จะเกิดอะไรขึ้นกับ==การดำเนินการ '' '? สมมติว่าเรามีวัตถุสองชิ้นIntegerที่มีค่าอยู่ภายในเท่ากัน พวกเขาจะเปรียบเทียบอย่างไร?
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println("i1==i2: "+(i1==i2));
ผลลัพธ์:
i1==i2: false

Кто бы сомневался... Сравниваются они How an objectы. А если так:Integer i1 = 1;
Integer i2 = 1;
System.out.println("i1==i2: "+(i1==i2));
ผลลัพธ์:
i1==i2: true
ตอนนี้มันน่าสนใจยิ่งขึ้น! ถ้าautoboxing-e ส่งคืนวัตถุเดียวกัน! นี่คือที่ที่มีกับดักอยู่ เมื่อเราพบว่าวัตถุเดิมถูกส่งกลับ เราจะเริ่มทดลองเพื่อดูว่าเป็นเช่นนั้นเสมอหรือไม่ และเราจะตรวจสอบกี่ค่า? หนึ่ง? สิบ? หนึ่งร้อย? เป็นไปได้มากว่าเราจะจำกัดตัวเองไว้ที่ร้อยในแต่ละทิศทางรอบศูนย์ และเราได้รับความเท่าเทียมกันทุกที่ ดูเหมือนว่าทุกอย่างจะดี อย่างไรก็ตาม มองย้อนกลับไปเล็กน้อยที่นี่ คุณเคยเดาบ้างไหมว่าสิ่งที่จับได้คืออะไร.. ใช่แล้ว อินสแตนซ์ของอ็อบเจ็กต์เชลล์ระหว่างการทำออโตบ็อกซ์นั้นถูกสร้างขึ้นโดยใช้วิธีการผลิต นี่เป็นตัวอย่างที่ดีจากการทดสอบต่อไปนี้:
public class AutoboxingTest {

    private static final int numbers[] = new int[]{-129,-128,127,128};

    public static void main(String[] args) {
        for (int number : numbers) {
            Integer i1 = number;
            Integer i2 = number;
            System.out.println("number=" + number + ": " + (i1 == i2));
        }
    }
}
ผลลัพธ์จะเป็นดังนี้:
number=-129: false
number=-128: true
number=127: true
number=128: false
สำหรับค่าที่อยู่ในช่วงแคชวัตถุที่เหมือนกันจะถูกส่งกลับ สำหรับผู้ที่อยู่นอกนั้น วัตถุที่แตกต่างกันจะถูกส่งกลับ ดังนั้นหากมีการเปรียบเทียบที่ไหนสักแห่งในเชลล์แอปพลิเคชันแทนที่จะเป็นแบบดั้งเดิม ก็มีโอกาสที่จะได้รับข้อผิดพลาดที่เลวร้ายที่สุด: ข้อผิดพลาดลอยตัว เนื่องจากโค้ดมักจะได้รับการทดสอบในช่วงค่าที่จำกัดซึ่งข้อผิดพลาดนี้จะไม่ปรากฏขึ้น แต่ในการทำงานจริงนั้นจะปรากฏหรือหายไปก็ได้ขึ้นอยู่กับผลการคำนวณบางประการ มันง่ายกว่าที่จะบ้ามากกว่าการพบข้อผิดพลาดเช่นนี้ ดังนั้นฉันขอแนะนำให้คุณหลีกเลี่ยงการออโต้บ็อกซ์ทุกครั้งที่เป็นไปได้ และนั่นไม่ใช่มัน จำคณิตศาสตร์ไว้ไม่เกินชั้นประถมศึกษาปีที่ 5 ปล่อยให้ความไม่เท่าเทียมกันA>=BและА<=B. สิ่งที่สามารถพูดเกี่ยวกับความสัมพันธ์AและB? มีเพียงสิ่งเดียวเท่านั้น - พวกเขาเท่าเทียมกัน คุณเห็นด้วยหรือไม่? ฉันคิดว่าใช่. มาทำการทดสอบกัน:
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println("i1>=i2: "+(i1>=i2));
System.out.println("i1<=i2: "+(i1<=i2));
System.out.println("i1==i2: "+(i1==i2));
ผลลัพธ์:
i1>=i2: true
i1<=i2: true
i1==i2: false
และนี่คือสิ่งที่แปลกประหลาดที่สุดสำหรับฉัน ฉันไม่เข้าใจเลยว่าทำไมคุณลักษณะนี้จึงถูกนำมาใช้ในภาษาถ้ามันทำให้เกิดความขัดแย้งดังกล่าว โดยทั่วไปฉันจะทำซ้ำอีกครั้ง - หากเป็นไปได้autoboxing/unboxingก็คุ้มค่าที่จะใช้โอกาสนี้อย่างเต็มที่ หัวข้อสุดท้ายที่ฉันอยากจะพูดถึงคือ... Java 5.0 การเปรียบเทียบองค์ประกอบการแจงนับ (ประเภทแจงนับ) ดังที่คุณทราบเนื่องจากเวอร์ชัน 5.0 Java ได้แนะนำประเภทเช่นแจงนับ - การแจงนับ โดยค่าเริ่มต้นอินสแตนซ์จะมีชื่อและหมายเลขลำดับในการประกาศอินสแตนซ์ในคลาส ดังนั้นเมื่อคำสั่งประกาศเปลี่ยนแปลงตัวเลขจึงเปลี่ยน อย่างไรก็ตาม ตามที่ฉันได้กล่าวไว้ในบทความ'การทำให้เป็นอนุกรมตามที่เป็นอยู่'สิ่งนี้ไม่ได้ทำให้เกิดปัญหา องค์ประกอบการแจงนับทั้งหมดมีอยู่ในสำเนาเดียว ซึ่งถูกควบคุมที่ระดับเครื่องเสมือน จึงสามารถเปรียบเทียบได้โดยตรงโดยใช้ลิงก์ * * * บางทีนั่นคือทั้งหมดสำหรับวันนี้เกี่ยวกับด้านการปฏิบัติของการเปรียบเทียบวัตถุ บางทีฉันอาจจะพลาดอะไรบางอย่างไป เช่นเคย ฉันรอคอยความคิดเห็นของคุณ! สำหรับตอนนี้ให้ฉันลาก่อน ขอขอบคุณทุกท่านที่ให้ความสนใจ! ลิงก์ไปยังแหล่งที่มา: การเปรียบเทียบวัตถุ: การปฏิบัติ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION