“สวัสดี อามีโก้!”
"สวัสดี ริชิ!"
“อืม วันนี้เป็นไงบ้าง”
"เยี่ยมมาก! วันนี้ Bilaabo บอกฉันเกี่ยวกับการเรียกซ้ำ และ Ellie บอกฉันเกี่ยวกับการอ้างอิงที่อ่อนแอและนุ่มนวล"
"เธอบอกคุณเกี่ยวกับการอ้างอิงผีหรือไม่"
"คุณกำลังพูดถึง PhantomReference ใช่ไหม เธอพูดถึงแต่ไม่ได้อธิบายรายละเอียด"
"เยี่ยมมาก ฉันหวังว่าคุณจะไม่ว่าอะไรถ้าฉันเติมเต็มช่องว่างนี้"
"แน่นอน! ฉันจะฟังคุณด้วยความยินดี Rishi!"
"เยี่ยมมาก งั้นฉันจะเริ่มแล้ว"
"การอ้างอิง Phantom เป็นการอ้างอิงที่อ่อนแอที่สุดของทั้งหมด มีผลเฉพาะเมื่อวัตถุไม่มีการอ้างอิงใด ๆ เลยนอกจากการอ้างอิง Phantom"

"PhantomReference ใช้ในขั้นตอนการลบออบเจกต์ที่ซับซ้อน นี่อาจจำเป็นเมื่อออบเจ็กต์ทำบางอย่างนอกเครื่อง Java เช่น เรียกฟังก์ชันระบบปฏิบัติการระดับต่ำหรือเขียนสถานะลงในไฟล์ หรือทำอย่างอื่นที่สำคัญมาก"
"ต่อไปนี้เป็นตัวอย่างของวิธีที่คุณอาจใช้:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomReference<Integer>> list = new ArrayList<PhantomReference<Integer>>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomReference<Integer>(x, queue));
}
"ฉันต้องการดึงความสนใจไปที่บรรทัดสุดท้ายอีกครั้ง ไม่เพียงแต่ออบเจกต์ x จะถูกส่งไปยัง PhantomReference เท่านั้น แต่ยังมีคิวพิเศษของการอ้างอิงแบบ phantom ด้วย"
"ทำไมเราถึงต้องการคิวนี้"
“นั่นคือสิ่งที่ฉันจะบอกเธอในตอนนี้”
"เมื่อคุณทำลายวัตถุที่อ้างอิงถึงผี มันจะถูกทำลาย แต่มันไม่ได้ถูกลบออกจากความทรงจำ! คุณคิดยังไงกับเรื่องนั้น!"
"แล้วมันทำงานยังไง"
"มีความแตกต่างเล็กน้อยที่นี่ ดังนั้นฉันจะเริ่มต้นด้วยสิ่งที่ง่ายที่สุด"
"หากเหลือแต่การอ้างอิงแบบหลอนถึงวัตถุ สิ่งนั้นจะเกิดขึ้นกับวัตถุนั้น:"
" ขั้นตอนที่ 1ในระหว่างการรวบรวมขยะครั้งต่อไป เมธอด Finalize() จะถูกเรียกใช้บนออบเจกต์ แต่ถ้าเมธอด Finalize() ยังไม่ถูกแทนที่ ขั้นตอนนี้จะถูกข้ามไป และขั้นตอนที่ 2 จะถูกดำเนินการทันที"
" ขั้นตอนที่ 2ในระหว่างการรวบรวมขยะครั้งต่อไป ออบเจกต์จะถูกวางในคิวพิเศษของออบเจกต์หลอน มันจะถูกลบออกจากคิวนี้เมื่อเมธอด clear() ถูกเรียกบน PhantomReference"
"ใครโทรมา วัตถุถูกลบไปแล้วใช่ไหม"
"อืม วัตถุนั้นได้ตายไปแล้วจริงๆ ในโลกของเรา (โลกของ Java) แต่มันไม่ได้หายไป มันยังคงเป็นผีอยู่ — คิวของวัตถุหลอนยังคงมีการอ้างอิงถึงมัน ReferenceQueueเดียวกันกับที่เราอ้างอิงอย่างระมัดระวัง ผ่านไปยัง ตัวสร้าง PhantomReference "
"ดังนั้น ReferenceQueue นี้จึงเปรียบเสมือนชีวิตหลังความตาย"
"เหมือนโลกหลอนมากกว่า"
"และวัตถุหลอนสามารถลบได้โดยการเรียก clear() ในการอ้างอิงผีเท่านั้น"
"นี่คือวิธีดำเนินการต่อจากตัวอย่างก่อนหน้านี้:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomReference<Integer>> list = new ArrayList<PhantomReference<Integer>>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomReference<Integer>(x, queue));
}
// Call the garbage collector and hope it will listen to us :)
// It should destroy all phantom reachable objects and put them in the queue
// of phantoms
System.gc();
// Get all objects from the queue
Reference<? extends Integer>referenceFromQueue;
while ((referenceFromQueue = queue.poll()) != null)
{
// Display the object on the screen
System.out.println(referenceFromQueue.get());
// Clear the reference
referenceFromQueue.clear();
}
"ฉันเข้าใจว่ามีบางอย่างเกิดขึ้นที่นี่ ฉันเกือบจะเข้าใจว่าเกิดอะไรขึ้นด้วยซ้ำ"
"แต่คุณจะใช้สิ่งนี้ในทางปฏิบัติได้อย่างไร"
"นี่คือตัวอย่างที่ดีกว่า:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomInteger> list = new ArrayList<PhantomInteger>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomInteger (x, queue));
}
Thread referenceThread = new Thread()
{
public void run()
{
while (true)
{
try
{
// Get the new object from the queue. If there is no object, then we wait!
PhantomInteger ref = (PhantomInteger)queue.remove();
// Call the close method on it
ref.close();
ref.clear();
}
catch (Exception ex)
{
// Write errors to a log
}
}
}
};
// Run the thread as a daemon
referenceThread.setDaemon(true);
referenceThread.start();
static class PhantomInteger extends PhantomReference<Integer>
{
PhantomInteger(Integer referent, ReferenceQueue<? super Integer> queue)
{
super(referent, queue);
}
private void close()
{
System.out.println("Bad Integer totally destroyed!");
}
}
"เราทำสามสิ่งที่นี่"
"อันดับแรก เราสร้าง คลาส PhantomIntegerซึ่งสืบทอดPhantomReference < Integer >"
"ประการที่สอง คลาสนี้มี เมธอด close () พิเศษ ความต้องการเรียกใช้เมธอดนี้คือสิ่งที่ทำให้ทั้งหมดนี้เริ่มต้นขึ้น
"ประการที่สาม เราประกาศเธรดพิเศษ: referenceThreadมันรอวนซ้ำจนกว่าออบเจกต์อื่นจะปรากฏในคิวผี ทันทีที่สิ่งนี้เกิดขึ้น เธรดจะลบออบเจ็กต์ออกจากคิวผีและเรียกใช้เมธอด close () จากนั้น วิธีการ clear() แค่นั้น ผีสามารถไปสู่โลกที่ดีกว่าได้ มันจะไม่รบกวนเราอีกต่อไป "
"น่าสนใจมาก แต่ทุกอย่างก็เรียบร้อย"
"เรากำลังติดตามคิวของวัตถุที่กำลังจะตาย และจากนั้นเราสามารถเรียกใช้วิธีการพิเศษสำหรับวัตถุแต่ละชิ้นได้"
"แต่จำไว้ว่า คุณไม่สามารถเรียกใช้เมธอดบนออบเจกต์ได้ คุณไม่สามารถรับการอ้างอิงถึงมันได้ เมธอด get() ของ PhantomReference จะคืนค่า null เสมอ "
"แต่เราสืบทอด PhantomReference!"
"แม้จะอยู่ในคลาสย่อยของ PhantomReference เมธอด get() จะคืนค่า null"
"ดังนั้นฉันจึงบันทึกการอ้างอิงถึงวัตถุในตัวสร้าง"
"อา แต่การอ้างอิงดังกล่าวจะเป็น StrongReference และวัตถุจะไม่มีวันจบลงในคิวหลอน!"
“แดง โอเค ยอมแพ้ ถ้ามันเป็นไปไม่ได้ มันก็เป็นไปไม่ได้”
"โอเค ดี ฉันหวังว่าคุณจะได้เรียนรู้สิ่งที่มีค่าจากบทเรียนวันนี้"
"ใช่ มีเนื้อหาใหม่ๆ มากมาย และฉันคิดว่าฉันรู้ทุกอย่างแล้ว ขอบคุณสำหรับบทเรียน ริชิ"
“ไม่เป็นไร แค่นี้แหละ ไปพักผ่อนเถอะ แต่อย่าลืมนะ เย็นนี้เรามีเรียนอีกคาบ”
GO TO FULL VERSION