"Hai, Amigo!"

"Hai, Rishi!"

"Nah, bagaimana hari anda?"

"Brilliant! Hari ini Bilaabo memberitahu saya tentang rekursi, dan Ellie memberitahu saya tentang rujukan yang lemah dan lembut."

"Adakah dia memberitahu anda tentang rujukan hantu?"

"Adakah anda bercakap tentang PhantomReference? Dia menyebutnya, tetapi tidak menerangkannya secara terperinci."

"Bagus, saya harap awak tidak keberatan jika saya mengisi jurang ini."

"Sudah tentu! Saya akan mendengar anda dengan senang hati, Rishi!"

"Bagus. Kalau begitu saya akan mulakan."

"Rujukan hantu ialah rujukan paling lemah daripada semua rujukan. Rujukan tersebut hanya mempunyai kesan jika objek tidak mempunyai sebarang rujukan sama sekali selain rujukan hantu."

Rujukan Phantom - 1

"PhantomReference digunakan dalam prosedur pemadaman objek yang kompleks.  Ini mungkin diperlukan apabila objek melakukan sesuatu di luar mesin Java, contohnya ia memanggil fungsi OS peringkat rendah atau menulis keadaannya pada fail atau melakukan sesuatu yang sangat penting."

"Berikut ialah contoh cara anda boleh menggunakannya:"

Contoh mencipta rujukan hantu
// 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));
}

"Saya mahu menarik perhatian kepada baris terakhir sekali lagi. Bukan sahaja objek x dihantar ke PhantomReference — baris gilir khas rujukan hantu juga."

"Kenapa kita perlukan barisan ini?"

"Itulah yang saya akan beritahu awak sekarang."

"Apabila anda memusnahkan objek yang dipegang oleh rujukan hantu, ia akan musnah, tetapi ia tidak dipadamkan daripada ingatan! Apa pendapat anda tentang itu?!"

"Jadi, bagaimana ia berfungsi?"

"Terdapat beberapa nuansa di sini, jadi saya akan mulakan dengan yang paling mudah."

"Jika hanya rujukan hantu kepada objek kekal, maka inilah yang akan berlaku kepadanya:"

" Langkah 1 . Semasa pengumpulan sampah seterusnya, kaedah finalize() akan dipanggil pada objek. Tetapi, jika kaedah finalize() belum ditindih, maka langkah ini dilangkau dan langkah 2 dilaksanakan serta-merta."

" Langkah 2 . Semasa kutipan sampah seterusnya, objek diletakkan dalam baris gilir khas objek hantu. Ia akan dipadamkan daripada baris gilir ini apabila kaedah clear() dipanggil pada PhantomReference."

"Siapa yang panggil? Objek itu telah dipadamkan, kan?"

"Nah, objek itu memang mati di dunia kita (dunia Jawa), tetapi ia tidak hilang. Ia kekal sebagai hantu — barisan objek hantu masih memegang rujukan kepadanya. ReferenceQueue yang sama yang rujukannya kami berhati- hati . diserahkan kepada pembina PhantomReference ."

"Jadi ReferenceQueue ni macam alam akhirat?"

"Lebih seperti dunia hantu."

"Dan objek hantu hanya boleh dipadamkan dengan memanggil clear() pada rujukan hantunya."

"Berikut ialah cara meneruskan contoh sebelumnya:"

Contoh mencipta rujukan hantu
// 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();
}

"Saya faham ada sesuatu yang berlaku di sini. Saya hampir faham apa yang sedang berlaku."

"Tetapi bagaimana anda menggunakan ini dalam amalan?"

"Ini contoh yang lebih baik:"

Contoh mencipta rujukan hantu
// 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));
}
Benang ini akan memantau baris gilir hantu dan mengalih keluar objek daripadanya
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();
Ini ialah kelas yang mewarisi PhantomReference dan mempunyai kaedah close().
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!");
 }
}

"Kami melakukan tiga perkara di sini."

"Pertama, kami mencipta kelas PhantomInteger , yang mewarisi PhantomReference < Integer >."

"Kedua, kelas ini mempunyai kaedah tutup () khas. Keperluan untuk memanggil kaedah ini adalah yang menyebabkan semua ini bermula.

"Ketiga, kami mengisytiharkan utas khas: referenceThread . Ia menunggu dalam gelung sehingga objek lain muncul dalam baris gilir hantu. Sebaik sahaja ini berlaku, utas itu mengalih keluar objek daripada baris gilir hantu dan memanggil kaedah tutupnya () dan kemudian kaedah clear(). Dan itu sahaja. Hantu boleh bergerak ke dunia yang lebih baik. Ia tidak lagi menyusahkan kita dalam dunia kita."

"Sangat menarik, tetapi semuanya berjaya."

"Kami sebenarnya menjejaki barisan objek yang mati, dan kemudian kami boleh memanggil kaedah khas untuk setiap daripada mereka."

"Tetapi ingat, anda tidak boleh memanggil kaedah pada objek itu sendiri.  Anda tidak boleh mendapatkan rujukan kepadanya! Kaedah get() PhantomReference sentiasa mengembalikan nol. "

"Tetapi kami mewarisi PhantomReference!"

"Walaupun dalam subkelas PhantomReference, kaedah get() mengembalikan null."

"Jadi saya hanya menyimpan rujukan kepada objek dalam pembina"

"Ah. Tetapi rujukan sebegitu akan menjadi StrongReference, dan objek itu tidak akan berakhir dalam baris gilir hantu!"

"Dang. Okay, give up. Kalau tak boleh, tak mungkin."

"Okay, bagus. Saya harap awak telah belajar sesuatu yang berharga daripada pelajaran hari ini."

"Ya, ada banyak bahan baru. Dan saya rasa saya sudah tahu segala-galanya. Terima kasih atas pengajarannya, Rishi."

"Sama-sama. Itu sahaja, pergi berehat. Tapi jangan lupa — kita ada pelajaran lain petang ini."