วิธีการสรุป อินเทอร์เฟซที่ปิดได้ และคำสั่ง try-with-resources (Java 7) - 1

“สวัสดี อามีโก้!”

"ฉันเพิ่งตัดสินใจที่จะหารือเกี่ยวกับ วิธี สุดท้าย () กับคุณ"

"ถ้าคุณจำได้ Finalize() เป็นเมธอดพิเศษที่วัตถุเรียกก่อนที่ตัวรวบรวมขยะจะทำลายมัน"

"จุดประสงค์หลักของวิธีนี้คือการเพิ่มทรัพยากรภายนอกที่ไม่ใช่ Java ที่ใช้โดยการปิดไฟล์ สตรีม I/O และอื่นๆ"

"น่าเสียดายที่วิธีนี้ไม่เป็นไปตามที่เราคาดไว้ Java virtual machine สามารถเลื่อนการทำลายอ็อบเจกต์ได้ เช่นเดียวกับการเรียกใช้เมธอดสุดท้าย ตราบใดที่มันต้องการ ยิ่งกว่านั้น มันไม่ได้รับประกันว่าวิธีนี้จะได้ผล เรียกเลย มีสถานการณ์มากมายที่ไม่ถูกเรียก ทั้งหมดนี้อยู่ในชื่อ «การเพิ่มประสิทธิภาพ»"

"ฉันมีข้อมูลอ้างอิงสองรายการสำหรับคุณ:"

Joshua Bloch ได้เขียนบทความที่ดีเกี่ยวกับวิธีนี้: ลิงก์
ฉันจะถอดความข้อความที่ตัดตอนมาสั้นๆ:

  1. Finalize() สามารถใช้ได้ในสองกรณีเท่านั้น:
    1. สำหรับการตรวจสอบหรือล้างทรัพยากรด้วยการบันทึก
    2. เมื่อทำงานกับรหัสเนทีฟที่ไม่สำคัญต่อการรั่วไหลของทรัพยากร
  2. Finalize() ทำให้ GC ช้าลง 430 เท่าในการทำความสะอาดวัตถุ
  3. Finalize() อาจไม่ถูกเรียก
ถ้าฉันพูดในการสัมภาษณ์ว่า Finalize เป็นไม้ยันรักแร้ที่ร้ายกาจและอันตราย ซึ่งการมีอยู่ของมันทำให้เกิดความสับสน ฉันจะพูดถูกไหม?

“นั่นทำให้วันของฉันดีขึ้น เอลลี่”

"Java 7 มีคำสั่งใหม่เพื่อแทนที่เมธอด endizeซึ่งเรียกว่าtry-with-resourcesมันไม่ใช่การแทนที่finalizeแต่เป็นวิธีทางเลือก"

"มันเหมือนกับการลองจับ แต่มีทรัพยากรหรือไม่"

"เกือบจะเหมือนกับการ try-catchสิ่งต่าง ๆ คือไม่เหมือนกับเมธอดFinalize () บล็อก สุดท้ายใน คำสั่ง try- catch-finalจะถูกดำเนินการเสมอ โปรแกรมเมอร์ยังใช้เทคนิคนี้เมื่อต้องการเพิ่มทรัพยากร ปิดเธรด ฯลฯ

"นี่คือตัวอย่าง:"

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read();
}
finally
{
 if (is != null)
 is.close();
}

"ไม่ว่า บล็อก tryจะดำเนินการอย่างถูกต้องหรือมีข้อยกเว้น บล็อก สุดท้ายจะถูกเรียกเสมอ และเป็นไปได้ที่จะปล่อยทรัพยากรที่ถูกครอบครองที่นั่น"

"ดังนั้นใน Java 7 จึงมีการตัดสินใจที่จะทำให้แนวทางนี้เป็นทางการ เช่น:"

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read();
}

" คำสั่งการลองแบบ พิเศษนี้ เรียกว่าการลองใช้ทรัพยากร

"โปรดสังเกตว่าหลังจากการ try จะมีวงเล็บซึ่งมีการประกาศตัวแปรและสร้างวัตถุ วัตถุเหล่านี้สามารถใช้ภายในบล็อกการลองที่ระบุโดยวงเล็บปีกกา เมื่อการดำเนินการบล็อกการพยายามเสร็จสิ้นไม่ว่าจะสิ้นสุดตามปกติหรือตรงนั้น เป็นข้อยกเว้น วิธีการปิด () จะถูกเรียกบนวัตถุใด ๆ ที่สร้างขึ้นภายในวงเล็บ"

"น่าสนใจจัง! เครื่องหมายนี้กระชับกว่าอันที่แล้วมาก ฉันยังไม่แน่ใจว่าจะเข้าใจไหม"

"ไม่ยากอย่างที่คิด"

"ฉันสามารถระบุคลาสของแต่ละวัตถุในวงเล็บได้หรือไม่"

"ใช่ แน่นอน มิฉะนั้นวงเล็บจะมีประโยชน์เพียงเล็กน้อย"

"และถ้าฉันต้องการเรียกใช้เมธอดอื่นหลังจากออกจากบล็อกลอง ฉันจะใส่ไว้ที่ไหน"

"สิ่งต่าง ๆ ละเอียดขึ้นเล็กน้อยที่นี่ Java 7 แนะนำอินเทอร์เฟซต่อไปนี้:"

public interface AutoCloseable
{
 void close() throws Exception;
}

"คลาสของคุณสามารถใช้อินเทอร์เฟซนี้ จากนั้นคุณสามารถใช้วัตถุภายในคำสั่ง try-with-resources ได้ เฉพาะวัตถุดังกล่าวเท่านั้นที่สามารถสร้างได้ภายในวงเล็บของคำสั่ง try-with-resource สำหรับ «ปิดอัตโนมัติ»"

"กล่าวอีกนัยหนึ่ง ฉันต้องแทนที่เมธอด close และเขียนโค้ดในนั้นเพื่อ «ล้างข้อมูล» วัตถุของฉัน และฉันไม่สามารถระบุเมธอดอื่นได้"

"ใช่ แต่คุณสามารถระบุวัตถุหลายชิ้นได้ เพียงแค่คั่นด้วยเครื่องหมายอัฒภาค:"

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read();
 os.write();
}

"ดีขึ้น แต่ไม่เจ๋งเท่าที่ฉันหวังไว้"

“ก็ไม่แย่เท่าไหร่ เดี๋ยวก็ชินเอง เมื่อเวลาผ่านไป”