Ferdiggjøringsmetoden, lukkbart grensesnitt og prøv-med-ressurser (Java 7) - 1

"Hei, Amigo!"

"Jeg bestemte meg for å diskutere finaliseringsmetoden ( ) med deg."

"Hvis du husker, er finalize() en spesiell metode som kalles opp av et objekt før søppelsamleren ødelegger det."

"Denne metodens hovedformål er å frigjøre brukte eksterne ikke-Java-ressurser ved å lukke filer, I/O-strømmer og så videre."

"Dessverre lever ikke denne metoden opp til våre forventninger. Den virtuelle Java-maskinen kan utsette å ødelegge et objekt, samt kalle finalize-metoden, så lenge den vil. Dessuten garanterer den ikke at denne metoden blir kalt i det hele tatt. Det er mange situasjoner der det ikke blir kalt, alt i «optimaliseringens navn».

"Jeg har to referanser til deg:"

Joshua Bloch har skrevet en god artikkel om denne metoden: lenke
Jeg vil omskrive et kort utdrag:

  1. finalize() kan bare brukes i to tilfeller:
    1. For å verifisere eller rydde opp i ressurser med logging.
    2. Når du arbeider med innfødt kode som ikke er kritisk for ressurslekkasjer.
  2. finalize() gjør GC 430 ganger tregere til å rydde opp i objekter
  3. finalize() kalles kanskje ikke
Hvis jeg i et intervju sier at finalisering er en skadelig og farlig krykke hvis eksistens er forvirrende, ville jeg ha rett?

"Vel, det gjorde dagen min, Ellie."

"Java 7 har en ny uttalelse for å erstatte finalize- metoden. Det kalles prøv-med-ressurser . Det er egentlig ikke en erstatning for finalize , snarere er det en alternativ tilnærming."

"Er det som try-catch, men med ressurser?"

"Det er nesten som try-catch . Tingene er, i motsetning til finalize ()-metoden, blir endelig blokken i en try- catch-finally- setning alltid utført. Programmerere har også brukt denne teknikken når de har trengt å frigjøre ressurser, lukk tråder osv.

"Her er et eksempel:"

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

"Uansett om prøveblokken ble utført riktig eller det var et unntak, vil den endelige blokken alltid bli kalt, og det er mulig å frigjøre okkuperte ressurser der."

"Så, i Java 7 ble beslutningen tatt om å gjøre denne tilnærmingen offisiell, slik:"

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

"Denne spesielle try- setningen kalles try-with-resources (ligner på hvordan samlinger har et alternativ for kalt foreach )."

"Legg merke til at etter forsøket er det parenteser der variabler deklareres og objekter opprettes. Disse objektene kan brukes inne i prøveblokken angitt med krøllete parenteser. Når prøveblokken er ferdig utført, uavhengig av om den endte normalt eller der var et unntak, vil close()-metoden bli kalt på alle objekter som er opprettet innenfor parentesen."

"Så interessant! Denne notasjonen er langt mer kompakt enn den forrige. Jeg er ikke sikker på om jeg forstår den ennå."

"Det er ikke så vanskelig som du tror."

"Så, kan jeg spesifisere klassen til hvert objekt i parentes?"

— Ja, selvfølgelig, ellers ville parentesen være til liten nytte.

"Og hvis jeg trenger å ringe en annen metode etter å ha avsluttet prøveblokken, hvor skal jeg legge den?"

"Ting er litt mer subtilt her. Java 7 introduserer følgende grensesnitt:"

public interface AutoCloseable
{
 void close() throws Exception;
}

"Klassen din kan implementere dette grensesnittet. Og så kan du bruke objektene i en try-with-resources-setning. Bare slike objekter kan opprettes innenfor parentesen til en try-with-resources-setning for «automatisk lukking».

"Med andre ord, jeg må overstyre lukkemetoden og skrive kode i den for å «rydde opp» objektet mitt, og jeg kan ikke spesifisere en annen metode?"

"Jepp. Men du kan spesifisere flere objekter - bare skille dem med semikolon:"

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

"Det er bedre, men ikke så kult som jeg hadde håpet."

"Det er ikke så ille. Du blir vant til det. Med tiden."