"Hej, Amigo!"

"Hej Rishi!"

"Jaha, hur var din dag?"

"Briljant! Idag berättade Bilaabo om rekursion, och Ellie berättade om svaga och mjuka referenser."

"Har hon berättat om fantomreferenser?"

"Pratar du om PhantomReference? Hon nämnde det, men förklarade det inte i detalj."

"Bra, då hoppas jag att du inte har något emot om jag fyller det här tomrummet."

"Självklart! Jag ska lyssna på dig med nöje, Rishi!"

"Jättebra. Då börjar jag."

"Fantomreferenser är de svagaste referenserna av alla. De har effekt endast om ett objekt inte har några andra referenser än fantomreferenser."

PhantomReference - 1

"En PhantomReference används i en komplex raderingsprocedur för objekt.  Detta kan vara nödvändigt när ett objekt gör något utanför Java-maskinen, t.ex. anropar OS-funktioner på låg nivå eller skriver sitt tillstånd till en fil eller gör något annat mycket viktigt."

"Här är ett exempel på hur du kan använda det:"

Exempel på att skapa fantomreferenser
// 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));
}

"Jag vill uppmärksamma den sista raden igen. Inte bara skickas objekt x till PhantomReference - en speciell kö av fantomreferenser är det också."

"Varför behöver vi denna kö?"

"Det är vad jag ska berätta nu."

"När du förstör ett föremål som hålls av en fantomreferens, förstörs det, men det raderas inte från minnet! Vad tycker du om det?!"

"Så, hur fungerar det?"

"Det finns ganska många nyanser här, så jag börjar med det enklaste."

"Om bara fantomreferenser till ett objekt finns kvar, så är detta vad som kommer att hända med det:"

" Steg 1. Under nästa sophämtning kommer finalize()-metoden att anropas på objektet. Men om finalize()-metoden inte har åsidosatts, hoppas detta steg över, och steg 2 exekveras omedelbart."

" Steg 2. Under nästa sophämtning placeras objektet i en speciell kö av fantomobjekt. Det kommer att raderas från denna kö när clear()-metoden anropas på PhantomReference."

"Vem kallar det? Objektet togs bort, eller hur?"

"Tja, objektet dog verkligen i vår värld (Java-världen), men det har inte försvunnit. Det finns kvar som ett fantom - kön av fantomobjekt har fortfarande en referens till det. Samma referenskö vars referens vi noggrant skickas till PhantomReference -konstruktorn."

"Så den här ReferenceQueue är som livet efter detta?"

"Mer som en fantomvärld."

"Och ett fantomobjekt kan bara tas bort genom att anropa clear() på dess fantomreferens."

"Så här fortsätter du med föregående exempel:"

Exempel på att skapa fantomreferenser
// 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();
}

"Jag förstår att något händer här. Jag förstår nästan till och med exakt vad som händer."

"Men hur använder man detta i praktiken?"

"Här är ett bättre exempel:"

Exempel på att skapa fantomreferenser
// 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));
}
Den här tråden kommer att övervaka fantomkön och ta bort objekt från den
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();
Detta är en klass som ärver PhantomReference och har en close()-metod
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!");
 }
}

"Vi gjorde tre saker här."

"Först skapade vi PhantomInteger- klassen, som ärver PhantomReference < Integer >."

"För det andra har den här klassen en speciell close ()-metod. Behovet av att anropa denna metod är det som fick allt detta igång.

"För det tredje deklarerade vi en speciell tråd: referenceThread . Den väntar i en loop tills ett annat objekt dyker upp i fantomkön. Så fort detta händer tar tråden bort objektet från fantomkön och anropar dess close ()-metod. Och sedan clear()-metoden. Och det är det. Fantomen kan gå vidare till en bättre värld. Den kommer inte längre att bekymra oss i vår."

"Så intressant, men allt löste sig."

"Vi spårar faktiskt en kö av döende föremål, och sedan kan vi anropa en speciell metod för vart och ett av dem."

"Men kom ihåg, du kan inte anropa metoden på själva objektet.  Du kan inte få en referens till det! PhantomReferences get()-metod returnerar alltid null. "

"Men vi ärver PhantomReference!"

"Även inom en underklass av PhantomReference returnerar get()-metoden null."

"Så jag sparar bara en referens till objektet i konstruktorn"

"Ah. Men en sådan referens skulle vara en StrongReference, och objektet kommer aldrig att hamna i fantomkön!"

"Dang. Okej, ge upp. Om det är omöjligt, då är det omöjligt."

"Okej, bra. Jag hoppas att du har lärt dig något värdefullt från dagens lektion."

"Ja, det var så mycket nytt material. Och jag trodde att jag redan visste allt. Tack för lektionen, Rishi."

"Du är välkommen. Det var allt, slappna av. Men glöm inte - vi har en lektion till i kväll."