"Hei, Amigo!"

"Hei, Rishi!"

"Vel, hvordan var dagen din?"

"Strålende! I dag fortalte Bilaabo meg om rekursjon, og Ellie fortalte meg om svake og myke referanser."

"Fortalte hun deg om fantomreferanser?"

"Snakker du om PhantomReference? Hun nevnte det, men forklarte det ikke i detalj."

"Flott, da håper jeg du ikke har noe imot at jeg fyller dette gapet."

"Selvfølgelig! Jeg vil høre på deg med glede, Rishi!"

"Flott. Da begynner jeg."

"Fantomreferanser er de svakeste referansene av alle. De har effekt bare hvis et objekt ikke har noen referanser i det hele tatt annet enn fantomreferanser."

PhantomReference - 1

"En PhantomReference brukes i en kompleks objektslettingsprosedyre.  Dette kan være nødvendig når et objekt gjør noe utenfor Java-maskinen, for eksempel kaller det lavnivå OS-funksjoner eller skriver tilstanden til en fil eller gjør noe annet veldig viktig."

"Her er et eksempel på hvordan du kan bruke det:"

Eksempel på å lage fantomreferanser
// 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));
}

"Jeg vil trekke oppmerksomheten til den siste linjen igjen. Ikke bare sendes objekt x til PhantomReference - en spesiell kø med fantomreferanser er det også."

"Hvorfor trenger vi denne køen?"

"Det er det jeg skal fortelle deg nå."

"Når du ødelegger et objekt som holdes av en fantomreferanse, blir det ødelagt, men det blir ikke slettet fra minnet! Hva tenker du om det?!"

"Så, hvordan fungerer det?"

"Det er ganske mange nyanser her, så jeg starter med det enkleste."

"Hvis bare fantomreferanser til et objekt gjenstår, så er dette hva som vil skje med det:"

" Trinn 1. Under neste søppelinnsamling vil finalize()-metoden bli kalt på objektet. Men hvis finalize()-metoden ikke har blitt overstyrt, hoppes dette trinnet over, og trinn 2 utføres umiddelbart."

" Trinn 2. Under neste søppelinnsamling plasseres objektet i en spesiell kø med fantomobjekter. Det vil bli slettet fra denne køen når clear()-metoden kalles på PhantomReference."

"Hvem kaller det? Objektet ble slettet, ikke sant?"

"Vel, objektet døde faktisk i vår verden (Java-verdenen), men det har ikke forsvunnet. Det forblir som et fantom - køen av fantomobjekter har fortsatt en referanse til det. Den samme ReferenceQueue hvis referanse vi nøye sendt til PhantomReference- konstruktøren."

"Så denne ReferenceQueue er som livet etter døden?"

"Mer som en fantomverden."

"Og et fantomobjekt kan bare slettes ved å ringe clear() på fantomreferansen."

"Slik fortsetter du med forrige eksempel:"

Eksempel på å lage fantomreferanser
// 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();
}

"Jeg forstår at noe skjer her. Jeg forstår nesten til og med nøyaktig hva som skjer."

— Men hvordan bruker du dette i praksis?

"Her er et bedre eksempel:"

Eksempel på å lage fantomreferanser
// 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));
}
Denne tråden vil overvåke fantomkøen og fjerne objekter fra 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();
Dette er en klasse som arver PhantomReference og har en close() metode
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 ting her.

"Først opprettet vi PhantomInteger- klassen, som arver PhantomReference < Integer >."

"For det andre har denne klassen en spesiell close ()-metode. Behovet for å kalle denne metoden er det som fikk alt dette i gang.

"For det tredje erklærte vi en spesiell tråd: referenceThread . Den venter i en løkke til et annet objekt dukker opp i fantomkøen. Så snart dette skjer, fjerner tråden objektet fra fantomkøen og kaller dens close () -metoden . Og så clear()-metoden. Og det er det. Fantomet kan gå videre til en bedre verden. Det vil ikke lenger plage oss i vår."

"Så interessant, men alt ordnet seg."

"Vi sporer faktisk en kø med døende gjenstander, og så kan vi kalle en spesiell metode for hver av dem."

"Men husk, du kan ikke kalle metoden på selve objektet.  Du kan ikke få en referanse til det! PhantomReferences get()-metode returnerer alltid null. "

"Men vi arver PhantomReference!"

"Selv innenfor en underklasse av PhantomReference returnerer get()-metoden null."

"Så jeg lagrer bare en referanse til objektet i konstruktøren"

"Ah. Men en slik referanse ville være en StrongReference, og objektet vil aldri havne i fantomkøen!"

"Dang. Ok, gi opp. Hvis det er umulig, så er det umulig."

"Ok, bra. Jeg håper du har lært noe verdifullt fra dagens leksjon."

"Ja, det var så mye nytt materiale. Og jeg trodde jeg allerede visste alt. Takk for leksjonen, Rishi."

"Du er velkommen. Det er det, slapp av. Men ikke glem - vi har en annen leksjon i kveld."