"Hallo Amigo!"

"Hallo Rishi!"

"Nou, hoe was je dag?"

"Briljant! Vandaag heeft Bilaabo me verteld over recursie en Ellie heeft me verteld over zwakke en zachte referenties."

'Heeft ze je verteld over fantoomreferenties?'

'Heb je het over PhantomReference? Ze noemde het, maar legde het niet in detail uit.'

"Geweldig, dan hoop ik dat je het niet erg vindt als ik dit gat opvul."

"Natuurlijk! Ik zal met plezier naar je luisteren, Rishi!"

"Geweldig. Dan zal ik beginnen."

"Fantoomreferenties zijn de zwakste referenties van allemaal. Ze hebben alleen effect als een object helemaal geen andere referenties heeft dan fantoomreferenties."

Fantoomreferentie - 1

"Een PhantomReference wordt gebruikt in een complexe procedure voor het verwijderen van objecten.  Dit kan nodig zijn wanneer een object iets doet buiten de Java-machine, het roept bijvoorbeeld OS-functies op laag niveau aan of schrijft zijn status naar een bestand of doet iets heel belangrijks."

"Hier is een voorbeeld van hoe u het zou kunnen gebruiken:"

Voorbeeld van het maken van fantoomreferenties
// 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));
}

"Ik wil nogmaals de aandacht vestigen op de laatste regel. Niet alleen wordt object x doorgegeven aan de PhantomReference , maar ook een speciale wachtrij met fantoomreferenties."

"Waarom hebben we deze wachtrij nodig?"

"Dat ga ik je nu vertellen."

"Wanneer je een object vernietigt dat wordt vastgehouden door een fantoomreferentie, wordt het vernietigd, maar wordt het niet uit het geheugen verwijderd! Wat vind je daarvan?!"

"Dus, hoe werkt dat?"

"Er zijn hier nogal wat nuances, dus ik zal beginnen met de eenvoudigste."

"Als er alleen fantoomverwijzingen naar een object overblijven, dan is dit wat ermee gebeurt:"

" Stap 1 . Tijdens de volgende opschoonactie wordt de methode finalize() aangeroepen voor het object. Maar als de methode finalize() niet is overschreven, wordt deze stap overgeslagen en wordt stap 2 onmiddellijk uitgevoerd."

" Stap 2. Tijdens de volgende opschoonactie wordt het object in een speciale wachtrij van fantoomobjecten geplaatst. Het wordt uit deze wachtrij verwijderd wanneer de methode clear() wordt aangeroepen op de PhantomReference."

"Wie roept het? Het object is verwijderd, toch?"

"Nou, het object stierf inderdaad in onze wereld (de Java-wereld), maar het is niet verdwenen. Het blijft als een fantoom - de rij fantoomobjecten bevat nog steeds een verwijzing ernaar. Dezelfde ReferenceQueue waarvan we de referentie zo zorgvuldig hebben gemaakt doorgegeven aan de PhantomReference -constructor."

"Dus deze ReferenceQueue is als het hiernamaals?"

"Meer als een fantoomwereld."

"En een fantoomobject kan alleen worden verwijderd door clear() aan te roepen op zijn fantoomreferentie."

"Zo gaat u verder met het vorige voorbeeld:"

Voorbeeld van het maken van fantoomreferenties
// 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();
}

"Ik begrijp dat hier iets gebeurt. Ik begrijp zelfs bijna precies wat er gebeurt."

"Maar hoe gebruik je dit in de praktijk?"

"Hier is een beter voorbeeld:"

Voorbeeld van het maken van fantoomreferenties
// 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));
}
Deze thread bewaakt de fantoomwachtrij en verwijdert er objecten uit
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();
Dit is een klasse die PhantomReference erft en een methode close() heeft
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!");
 }
}

"We hebben hier drie dingen gedaan."

"Eerst hebben we de klasse PhantomInteger gemaakt, die PhantomReference < Integer > erft."

"Ten tweede heeft deze klasse een speciale close () methode. De noodzaak om deze methode aan te roepen is wat dit alles in gang heeft gezet.

"Ten derde hebben we een speciale thread gedeclareerd: referenceThread . Het wacht in een lus totdat er een ander object in de phantom-wachtrij verschijnt. Zodra dit gebeurt, verwijdert de thread het object uit de fantoom-wachtrij en roept zijn methode close () aan. En dan de clear() methode. En dat is het. Het fantoom kan verder gaan naar een betere wereld. Het zal ons niet langer lastig vallen in de onze."

"Zo interessant, maar het is allemaal gelukt."

"We volgen eigenlijk een rij stervende objecten, en dan kunnen we voor elk daarvan een speciale methode aanroepen."

"Maar vergeet niet dat je de methode niet op het object zelf kunt aanroepen.  Je kunt er geen verwijzing naar krijgen! De methode get() van de PhantomReference geeft altijd null terug. "

"Maar we erven PhantomReference!"

"Zelfs binnen een subklasse van PhantomReference retourneert de methode get() null."

"Dus ik bewaar gewoon een verwijzing naar het object in de constructor"

"Ah. Maar zo'n referentie zou een StrongReference zijn, en het object zal nooit in de fantoomwachtrij terechtkomen!"

"Dang. Oké, geef het op. Als het onmogelijk is, dan is het onmogelijk."

"Oké, goed. Ik hoop dat je iets waardevols hebt geleerd van de les van vandaag."

"Ja, er was zoveel nieuw materiaal. En ik dacht dat ik alles al wist. Bedankt voor de les, Rishi."

'Graag gedaan. Dat was het, ga je lekker ontspannen. Maar vergeet niet - we hebben vanavond nog een les.'