จากประสบการณ์ของฉันมีเหตุผลเพียงหนึ่งเดียวเท่านั้นที่เอาชนะObject.finalize()
ได้ แต่เป็นเหตุผลที่ดีมาก :
ไปยังสถานที่รหัสข้อผิดพลาดในการเข้าสู่ที่แจ้งให้คุณทราบหากคุณลืมที่จะเรียกfinalize()
close()
การวิเคราะห์แบบสแตติกสามารถตรวจจับการละเว้นในสถานการณ์การใช้งานเล็กน้อยและคำเตือนของคอมไพเลอร์ที่กล่าวถึงในคำตอบอื่นมีมุมมองแบบง่าย ๆ ของสิ่งต่าง ๆ ที่คุณต้องปิดการใช้งานจริงเพื่อทำสิ่งที่ไม่สำคัญ (ฉันเปิดใช้งานคำเตือนมากกว่าโปรแกรมอื่น ๆ ที่ฉันรู้จักหรือเคยได้ยิน แต่ฉันไม่ได้เปิดใช้งานคำเตือนที่โง่)
การสรุปอาจดูเหมือนเป็นกลไกที่ดีในการตรวจสอบให้แน่ใจว่าทรัพยากรไม่ได้ขาดอะไรเลย แต่คนส่วนใหญ่เห็นว่ามันผิดไปโดยสิ้นเชิง: พวกเขาคิดว่ามันเป็นกลไกทางเลือกสำรองซึ่งเป็นการป้องกัน "โอกาสครั้งที่สอง" ซึ่งจะเป็นการ วันโดยการทิ้งทรัพยากรที่พวกเขาลืม นี้เป็นธรรมที่ตายแล้ว จะต้องมีวิธีเดียวในการทำสิ่งใดก็ตามไม่ว่าคุณจะปิดทุกอย่างเสมอไปหรือการปิดท้ายจะปิดทุกอย่างเสมอ แต่เนื่องจากการสรุปไม่น่าเชื่อถือการสรุปจึงไม่สามารถทำได้
จึงมีโครงการนี้ซึ่งผมเรียกการกำจัดบังคับและกำหนดให้โปรแกรมเมอร์เป็นผู้รับผิดชอบเสมออย่างชัดเจนปิดทุกอย่างที่ดำเนินการหรือCloseable
AutoCloseable
(ข้อความลองกับทรัพยากรยังนับเป็นการปิดอย่างชัดเจน) แน่นอนว่าโปรแกรมเมอร์อาจลืมดังนั้นการสรุปจึงเข้าสู่การเล่น แต่ไม่ใช่นางฟ้ามายากลซึ่งจะทำให้สิ่งที่น่าอัศจรรย์ในท้ายที่สุด: หากการค้นพบขั้นสุดท้าย ที่close()
ไม่ได้เรียกใช้ก็ไม่ได้พยายามที่จะเรียกใช้มันอย่างแม่นยำเพราะจะ (มีความแน่นอนทางคณิตศาสตร์) เป็นพยุหะของโปรแกรมเมอร์ n00b ที่จะพึ่งพามันในการทำงานที่พวกเขาขี้เกียจเกินไปหรือขาดสติที่จะทำ ดังนั้นเมื่อมีการกำจัดอย่างถูกต้องเมื่อพบว่าclose()
ไม่มีการเรียกใช้ขั้นสุดท้ายจะบันทึกข้อความแสดงข้อผิดพลาดสีแดงสดบอกโปรแกรมเมอร์ด้วยตัวพิมพ์ใหญ่ทุกตัวที่อ้วนเพื่อแก้ไขสิ่งที่เขาทำ
ในฐานะที่เป็นประโยชน์เพิ่มเติมมีข่าวลือว่า "JVM จะเพิกเฉยต่อวิธีสรุปผลเล็กน้อย (เช่นที่เพิ่งกลับมาโดยไม่ทำอะไรเช่นที่กำหนดไว้ในคลาส Object)" ดังนั้นด้วยการกำจัดบังคับคุณสามารถหลีกเลี่ยงการสรุปทั้งหมด ค่าใช้จ่ายในระบบทั้งหมดของคุณ ( ดูคำตอบของ alipสำหรับข้อมูลว่าค่าใช้จ่ายนี้แย่มากเพียงใด) โดยการเขียนโค้ดfinalize()
วิธีการของคุณดังนี้:
@Override
protected void finalize() throws Throwable
{
if( Global.DEBUG && !closed )
{
Log.Error( "FORGOT TO CLOSE THIS!" );
}
//super.finalize(); see alip's comment on why this should not be invoked.
}
ความคิดที่อยู่เบื้องหลังนี้คือGlobal.DEBUG
เป็นstatic final
ตัวแปรที่มีค่าเป็นที่รู้จักกันในเวลารวบรวมดังนั้นถ้ามันเป็นfalse
แล้วคอมไพเลอร์จะไม่ปล่อยรหัสใด ๆ เลยสำหรับทั้งif
คำสั่งซึ่งจะทำให้เรื่องนี้เป็นที่น่ารำคาญ (ว่าง) finalizer ซึ่งในทางกลับกัน หมายความว่าชั้นเรียนของคุณจะได้รับการปฏิบัติเสมือนว่าไม่มีผู้เข้ารอบสุดท้าย (ใน C # สามารถทำได้ด้วย#if DEBUG
บล็อกที่ดีแต่สิ่งที่เราทำได้คือ java ซึ่งเราจ่ายความเรียบง่ายที่ชัดเจนในโค้ดพร้อมค่าใช้จ่ายเพิ่มเติมในสมอง)
เพิ่มเติมเกี่ยวกับการกำจัดข้อบังคับที่มีการอภิปรายเพิ่มเติมเกี่ยวกับการกำจัดทรัพยากรใน dot Net ที่นี่: michael.gr: การกำจัดข้อบังคับและสิ่งที่น่ารังเกียจ "Dispos-dising"
finalize()
นั้นค่อนข้างสับสน หากคุณเคยใช้มันต้องแน่ใจว่ามันปลอดภัยสำหรับเธรดที่เกี่ยวข้องกับวิธีการอื่น ๆ ทั้งหมดในวัตถุเดียวกัน