Java >> Java tutorial >  >> Tag >> final

Guide til Java endelig søgeord

1. Oversigt

I denne øvelse vil vi udforske endelig nøgleord i Java. Vi vil se, hvordan du bruger det sammen med try/catch blokerer i fejlhåndtering. Skønt endelig er beregnet til at garantere eksekvering af kode, vil vi diskutere usædvanlige situationer, hvor JVM ikke eksekverer den.

Vi vil også diskutere nogle almindelige faldgruber, hvor en endelig blokering kan have et uventet udfald.

2. Hvad er endelig?

endelig definerer en kodeblok, vi bruger sammen med try søgeord. Den definerer kode, der altid køres efter forsøg og enhver fangst blok, før metoden er fuldført.

Den endelig blok udføres, uanset om en undtagelse er smidt eller fanget .

2.1. Et hurtigt eksempel

Lad os se på endelig  i en try-catch-endelig blokere:

try {
    System.out.println("The count is " + Integer.parseInt(count));
} catch (NumberFormatException e) {
    System.out.println("No count");
} finally {
    System.out.println("In finally");
}

I dette eksempel, uanset værdien af ​​parameteren count , udfører JVM'en endelig blokere og udskrive “Indelig” .

2.2. Bruger endelig Uden en fangst Bloker

Vi kan også bruge a endelig bloker med et forsøg blokere, uanset om en fangst blok er til stede :

try {
    System.out.println("Inside try");
} finally {
    System.out.println("Inside finally");
}

Og vi får outputtet:

Inside try
Inside finally

2.3. Hvorfor endelig Er nyttig

Vi bruger generelt endelig blok for at udføre oprydningskode som lukning af forbindelser, lukning af filer eller frigivelse af tråde, da den udføres uanset en undtagelse.

Bemærk: prøv-med-ressourcer kan også bruges til at lukke ressourcer i stedet for endelig blokere.

3. Når endelig Udføres

Lad os se på alle permutationerne for, hvornår JVM'en kører endelig blokke, så vi kan forstå det bedre.

3.1. Ingen undtagelse er kastet

Når forsøg blokering afsluttes, endelig  blok udføres, selvom der ikke var nogen undtagelse:

try {
    System.out.println("Inside try");
} finally {
    System.out.println("Inside finally");
}

I dette eksempel kaster vi ikke en undtagelse fra forsøg blok. Således udfører JVM al kode i både try og endelig blokerer.

Dette udsender:

Inside try
Inside finally

3.2. Undtagelse er smidt og ikke håndteret

Hvis der er en undtagelse, og den ikke fanges, vil endelig blokering udføres stadig:

try {
    System.out.println("Inside try");
    throw new Exception();
} finally {
    System.out.println("Inside finally");
}

JVM'et udførerendelig blokere selv i tilfælde af en ubehandlet undtagelse.

Og outputtet ville være:

Inside try
Inside finally
Exception in thread "main" java.lang.Exception

3.3. Undtagelse er smidt og håndteret

Hvis der er en undtagelse, og den fanges af fangsten blok, den endelig blokering udføres stadig:

try {
    System.out.println("Inside try");
    throw new Exception();
} catch (Exception e) {
    System.out.println("Inside catch");
} finally {
    System.out.println("Inside finally");
}

I dette tilfælde er fangsten blok håndterer den kastede undtagelse, og derefter udfører JVM'en endelig blokerer og producerer output:

Inside try
Inside catch
Inside finally

3.4. Metode vender tilbage fra try Bloker

Selv tilbagevenden fra metoden vil ikke forhindre endelig blokerer fra at køre:

try {
    System.out.println("Inside try");
    return "from try";
} finally {
    System.out.println("Inside finally");
}

Her, selvom metoden har et afkast sætning, udfører JVM'en endelig blokere, før kontrollen overdrages til opkaldsmetoden.

Vi får outputtet:

Inside try
Inside finally

3.5. Metode Returnerer fra fangst Bloker

Når fangsten blok indeholder en retur erklæring, endelig blok hedder stadig:

try {
    System.out.println("Inside try");
    throw new Exception();
} catch (Exception e) {
    System.out.println("Inside catch");
    return "from catch";
} finally {
    System.out.println("Inside finally");
}

Når vi kaster en undtagelse fra forsøg blok, fangsten blok håndterer undtagelsen. Selvom der er en returerklæring i fangsten blok, udfører JVM'en endelig blokere, før kontrollen overgives til opkaldsmetoden, og den udsender:

Inside try
Inside catch
Inside finally

4. Når endelig Udføres ikke

Selvom vi altid forventer, at JVM udfører sætningerne i en endelig blokerer, er der nogle situationer, hvor JVM'en ikke vil udføre en endelig blokere.

Vi forventer måske allerede, at hvis operativsystemet stopper vores program, så ville programmet ikke få chancen for at udføre al sin kode. Der er også nogle handlinger, vi kan foretage, som på samme måde forhindrer udførelsen af ​​en afventende endelig blokere.

4.1. Kalder System.exit

I dette tilfælde afslutter vi JVM ved at kalde System.exit og derfor vil JVM ikke udføre vores endelig blokere:

try {
    System.out.println("Inside try");
    System.exit(1);
} finally {
    System.out.println("Inside finally");
}

Dette udsender:

Inside try

4.2. Kalder stop

Svarende til System.exit , et opkald til Runtime.halt stopper også udførelsen, og JVM udfører ingen endelig blokke:

try {
    System.out.println("Inside try");
    Runtime.getRuntime().halt(1);
} finally {
    System.out.println("Inside finally");
}

Resultatet bliver således:

Inside try

4.3. Dæmontråd

Hvis en Daemon-tråd går ind i udførelsen af ​​en forsøg/endelig blok og alle andre ikke-dæmon-tråde afsluttes, før dæmontråden udfører endelig blokerer, venter JVM ikke på, at dæmontråden afslutter udførelsen af ​​endelig blokere:

Runnable runnable = () -> {
    try {
        System.out.println("Inside try");
    } finally {
        try {
            Thread.sleep(1000);
            System.out.println("Inside finally");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};
Thread regular = new Thread(runnable);
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
regular.start();
Thread.sleep(300);
daemon.start();

I dette eksempel er den kørbare udskriver "Prøv indeni" så snart den går ind i metoden og venter i 1 sekund, før den udskriver "Endelig inde" .

Her starter vi den almindelige tråden og dæmonen tråd med en lille forsinkelse. Når den almindelige tråden udfører endelig blok, dæmonen tråden venter stadig inden for forsøg blok. Som den almindelige tråd fuldfører eksekvering og afslutter, JVM afsluttes også og venter ikke på dæmonen tråd for at fuldføre endelig blokere.

Her er outputtet:

Inside try
Inside try
Inside finally

4.4. JVM når en uendelig sløjfe

Her er et forsøg blok, som indeholder en uendelig mens sløjfe:

try {
    System.out.println("Inside try");
    while (true) {
    }
} finally {
    System.out.println("Inside finally");
}

Selvom det ikke er specifikt for endelig , er det værd at nævne, at hvis forsøg eller fang blok indeholder en uendelig løkke, vil JVM aldrig nå nogen blok ud over den løkke.

5. Almindelige faldgruber

Der er nogle almindelige faldgruber, som vi skal undgå, når vi bruger endelig blokere.

Selvom det er helt lovligt, anses det for dårlig praksis at få retur sætning eller smid en undtagelse fra en endelig blokere, og vi bør undgå det for enhver pris.

5.1. Se bort fra undtagelsen

En retur erklæring i endelig blok ignorerer en ufanget undtagelse:

try {
    System.out.println("Inside try");
    throw new RuntimeException();
} finally {
    System.out.println("Inside finally");
    return "from finally";
}

I dette tilfælde ignorerer metoden RuntimeException kastet og returnerer værdien “fra endelig” .

5.2. Ignorerer Anden retur Udtalelser

En retur erklæring i endelig blok ignorerer enhver anden retursætning i forsøg eller fang blok. Kun return erklæring i endelig blok udfører:

try {
    System.out.println("Inside try");
    return "from try";
} finally {
    System.out.println("Inside finally");
    return "from finally";
}

I dette eksempel returnerer metoden altid “fra endelig” og ignorerer fuldstændig return sætning i forsøg blok. Dette kan være en meget svær fejl at få øje på, og derfor bør vi undgå at bruge returendelig blokerer.

5.3. Ændrer, hvad der kastes eller returneres

Også i tilfælde af at kaste en undtagelse fra en endelig blok, ignorerer metoden den afgivne undtagelse eller retur udsagn i try og fang blokke:

try {
    System.out.println("Inside try");
    return "from try";
} finally {
    throw new RuntimeException();
}

Denne metode returnerer aldrig en værdi og kaster altid en RuntimeException .

Selvom vi måske ikke med vilje smider en undtagelse fra endelig blokere som i dette eksempel, kan vi stadig støde på dette problem. Det kan forekomme, når oprydningsmetoder, vi bruger, endelig blokkast en undtagelse.

6. Konklusion

I denne artikel diskuterede vi hvad endelig blokke gør i Java, og hvordan man bruger dem. Derefter så vi på forskellige tilfælde, hvor JVM udfører dem, og nogle få, når det måske ikke var tilfældet.

Til sidst så vi på nogle almindelige faldgruber forbundet med at bruge endelig blokerer.

Som altid er kildekoden, der bruges i denne tutorial, tilgængelig på GitHub.


Java tag