Qual è la differenza tra il codice all'interno di una clausola finally e il codice posizionato dopo la clausola catch?

3

Il mio codice java è come sotto:

public void check()throws  MissingParamException{
    ......
}
public static void main(){
    PrintWriter out = response.getWriter();
    try {
        check();
    } catch (MissingParamException e) {
        // TODO Auto-generated catch block
        out.println("message:"+e.getMessage());
        e.printStackTrace();
        out.close();
    }finally{
        out.close();
    }
    //out.close();
}

Quindi, la mia confusione è: quale differenza se metto out.close() in un blocco di codice finalmente o se rimuovo finalmente il blocco di codice e metto out.close() dietro la clausola catch (che è stata commentata nel codice). So che in entrambi i modi, verrà eseguito out.close() perché so che se si è verificata l'eccezione, il codice dietro la clausola catch verrà sempre eseguito.

    
posta wuchang 18.10.2013 - 03:47
fonte

4 risposte

9

Il blocco finally {} è sempre chiamato (a meno che non chiami exit() prima che venga finalmente raggiunto - ma non lo farai quasi sempre).

Lo scopo finale è ripulire le risorse allocate nel blocco try {} , anche se è stato lanciato qualcosa e ha colpito il blocco catch{} .

Considera il codice:

public class Hello {

    public static void main(String[] args) {
        hello();
    }

    public static void hello() {
        try {
            System.out.println("hi");
            return;
        } catch (RuntimeException e) {
        } finally {
            System.out.println("finally");
        }
    }
}

Anche se non ci sono allocazioni di risorse in questo, fai finta che ci sia. Questo verrà stampato:

hi
finally

Se avevi aperto un file nel blocco try, finalmente è il posto giusto per ripulirlo. Se avevi aperto un file e poi hai provato ad aprirne un altro (che ha generato un'eccezione), finalmente è il posto giusto per ripulirlo.

Se c'è stata un'eccezione non rilevata dal blocco catch , verrà eseguito finally e l'eccezione verrà passata in su.

Mettere out.close() in catch e il finally è ridondante - perché verrà eseguito nel blocco finally - su un'eccezione rilevata o un completamento riuscito di try .

Con il codice esistente, sono possibili i seguenti percorsi di codice:

  • Nessuna eccezione:

    1. check () - nessuna eccezione generata
    2. finally {} - out.close
  • Eccezione rilevata:

    1. check () - MissingParamException generato
    2. catch {} - stuff e out.close
    3. finally {} - out.close
  • Eccezione non rilevata:

    1. check () - NPE generato
    2. finally {} - out.close

Dovresti essere in grado di vedere da questo, viene sempre chiamato finally , e nell'eccezione sorpresa out.close() viene invocato due volte.

Le specifiche associate sono §14.20.2 nelle specifiche del linguaggio Java SE 7.

    
risposta data 18.10.2013 - 04:01
fonte
8

La differenza è che se la tua funzione check () genera un'eccezione ALTRA rispetto a MissingParamException, qualsiasi cosa sotto try / catch non verrà eseguita perché lo stack della tua funzione verrà srotolato fino a che non verrà trovato un catch che gestirà quell'eccezione di quel tipo ( o eventualmente thread si chiude se l'eccezione non viene gestita). Tuttavia, il codice inserito nella clausola finally è garantito per essere eseguito indipendentemente da ciò che accade all'interno del blocco try.

Quindi nel tuo caso lasciare out.close () all'interno del blocco finally sarebbe una cosa più corretta da fare.

    
risposta data 18.10.2013 - 03:59
fonte
3

Facciamo l'analisi del caso.

  1. Nessuna eccezione generata:  Nessuna differenza
  2. MissingParamException generata:  Nessuna differenza
  3. Qualche eccezione che non hai catture per me. e. Rif. Nullo:  Se è in finalmente out.close () verrà chiamato. Se è dopo tutto allora non verrà chiamato.

    Per inciso si chiama close nel blocco catch e il blocco finally che indica quando viene lanciata MissingParamException si chiama close due volte. Non è un grosso problema, solo non necessario.

risposta data 18.10.2013 - 04:00
fonte
2

Alla maggior parte è stata data una risposta nelle altre risposte, ma una cosa non è: Se scegli di non usare finalmente e il tuo codice entra nel blocco catch e c'è un'altra eccezione nel blocco catch, non verrà chiamata nessuna chiusura.

    
risposta data 18.10.2013 - 04:22
fonte

Leggi altre domande sui tag