2015-10-13 12 views
18

Ho un programma come segue:try/finally senza valore delle catture e ritorno

public class Main { 
    public static void main(String[] args)throws Exception 
    { 
     int res = test(); 
     System.out.println("after call , res = " + res) ; 
    } 

    public static int test()throws Exception 
    { 
     try 
     { 
      return 10/0; 
     } 
     finally 
     { 
      System.out.println("finally") ; 
     } 
    } 
} 

dopo l'esecuzione di sopra del programma, seguente risultato ha visto in consolle:

finally 
Exception in thread "main" java.lang.ArithmeticException:/by zero 
    at Main.test(Main.java:17) 
    at Main.main(Main.java:7) 

questo comportamento è normale perché eccezione generata al metodo principale.

Poi modificare il codice come segue:

public class Main { 
    public static void main(String[] args)throws Exception 
    { 
     int res = test(); 
     System.out.println("after call , res = " + res) ; 
    } 

    public static int test()throws Exception 
    { 
     try 
     { 
      return 10/0; 
     } 
     finally 
     { 
      System.out.println("finally") ; 
      return 20; 
     } 
    } 
} 

Quando viene eseguito sopra il programma che ho visto seguente risultato in consolle:

finally 
after call , res = 20 

La mia domanda relativa al secondo formato. Perché quando ritorni finalmente in blocco, eccezione non generata al metodo principale?

+2

@Tunaki Non quello. –

+1

Questo forse: http://stackoverflow.com/q/48088/1743880? – Tunaki

+0

Si prega di dare un'occhiata: http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java – Rehman

risposta

7

Dalla JLS (sottolineatura mia):

Se l'esecuzione del blocco try completa bruscamente a causa di un lancio di un valore V, allora v'è una scelta:
[...]
Se il tipo di runtime di V non è compatibile con un'assegnazione di classe di eccezione catchable di qualsiasi clausola catch dell'istruzione try, viene eseguito il blocco finally . Poi v'è una scelta:

  • Se il blocco finally completa normalmente, allora l'istruzione try completa bruscamente a causa di un lancio del valore V.

  • Se il blocco finally completa bruscamente per la ragione S, quindi la dichiarazione di prova termina bruscamente per il motivo S (e il lancio del valore V è scartato e dimenticato).

TL/DR
Questo significa che se si return all'interno del blocco finally, il metodo restituisce, senza un'eccezione.
/TL/DR

Inoltre return, ci sono altri statementes che possono causare il blocco di finallycompleta bruscamente e dimenticare l'eccezione. Sono definiti nello JLS Section 14.1. Fondamentalmente, è break, continue, return o un'eccezione (generata o causata da un'istruzione/metodo). Il blocco try/catch/finally completo viene quindi completato con questo motivo.

Ci sono alcuni altri casi nella specifica di try/catch/finally, specialmente se non esiste un'eccezione o esiste una clausola di cattura corrispondente. Si riduce a finally battiti catch battiti try.

3
  1. Se si utilizza return nella sezione finally, si perde l'eccezione. Il metodo verrà completato con un tipo normale di valore restituito.
  2. Se non si utilizza return nella sezione finally, nel proprio caso, il metodo sarà terminato con eccezione.

Il primo caso:

try { 
    throw new Exception(); 
} finally { 
    //Exception will be lost, normal shutdown of the method 
    return; 
} 

Il secondo caso:

try { 
    throw new Exception(); 
} finally { 
    //Exception won't be lost, we'll get Exception in the main method 
} 

Il terzo caso:

try { 
    throw new Exception(); 
} finally { 
    throw new IOException(); 
    // we lost Exception, IOException will be thrown 
} 

Nota: Utilizzare la sezione finally per generare eccezioni o restituire valori è una cattiva pratica. Questa sezione è stata creata, ad esempio, per la chiusura di risorse esterne.

0

Java return non restituisce sempre, this potrebbe intrattenere.

13

Quando si genera la propria eccezione, , si passa prima al blocco finally.

Se il blocco finally non restituisce o invia nulla, viene inoltrata l'eccezione originale.

Se il blocco finally restituisce un valore, , l'eccezione non viene più propagata affatto.

2

Tutto in un blocco finally viene eseguito prima che viene lanciata l'eccezione, quindi se si torna in un blocco finally, l'eccezione non sarà gettato a tutti. In genere è una cattiva idea tornare dal blocco finale per questo motivo.

Date un'occhiata a this blog per alcune informazioni su questo.

8

Guarda l'esecuzione di try catch finalmente.

Da java language specification -jls-14.20.2

Se il tipo di runtime di V non è compatibile con l'assegnazione di una classe di eccezione catturabile di qualsiasi clausola catch dell'istruzione try, poi il blocco finally viene eseguito. Poi v'è una scelta:

Se il blocco finally completa normalmente, allora l'istruzione try completa bruscamente a causa di un lancio del valore V.

Se il blocco finally completa bruscamente per la ragione S, allora l'istruzione try completa bruscamente per il motivo S (e il lancio del valore V viene scartato e dimenticato).

+1

Mi chiedo solo, qual è la ragione S? – bvdb

+1

@bvdb In questo caso, l'eccezione. –

+1

@bvdb JLS 14.1: https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html; Sloppy ha detto: Può essere qualsiasi istruzione che impedisce al blocco di terminare alla sua parentesi finale: A 'break',' continue', 'return' o un'eccezione. – flo

0

Il ritorno statementin blocco finally era fondamentalmente fermando l'eccezione che è accaduto nel blocco try da propagare su anche se non è stato catturato.

Ma il compilatore Java notifica gli avvisi durante la scrittura di questo pezzo di codice. Sebbene return statements dovrebbe sempre si trovano in try block, e finally blocco è uasully per releasing/closing connections, pointers etc.

Sembra modo Java comporta.

Date un'occhiata here

0

Se leggete java doc di fine poi si dice,

che permette al programmatore di evitare di avere il codice di pulitura accidentalmente bypassato da un ritorno, continua, o rompersi. Mettere il codice di pulizia in un blocco finale è sempre una buona pratica, anche quando non sono previste eccezioni.

Quindi se si inserisce codice di pulitura dopo il blocco finally, non verrà chiamato se c'è un'eccezione.

0

Nel primo caso, il blocco finally viene eseguito come comportamento ma non ha rilevato l'eccezione ma l'eccezione viene generata tramite il metodo principale. Controllare tramite questo esempio

public class HelloWorld{ 

    public static void main(String []args)throws Exception 
    { 
     try 
     { 
     int res = test(); 
     System.out.println("after call , res = " + res) ; 
     } 
     catch(Exception ex) 
     { 
      System.out.println("Main Catch") ; 
     } 
    } 
    public static int test()throws Exception 
    { 
     try 
     { 
      return 10/0; 
     } 
     finally 
     { 
      System.out.println("finally") ; 
     } 
    } 
} 

Nel codice di cui sopra, ha fatto Main Catch giustiziati.

Nel secondo caso, è stato restituito il numero, quindi non c'era eccezione nel metodo principale.

0

Perché blocco finally viene sempre eseguito, se si verificano eccezioni o no, e se si torna da finalmente mezzi, si sta inviando la tua esecuzione al metodo chiamante e si perde l'eccezione. Quindi genera anche un avvertimento.

enter image description here

0

In primo programma quando ArithmeticException verificano nel blocco try quindi chiamare il blocco finally e dopo eseguire il blocco finally, si verificano eccezione. perché l'eccezione non è gestita dal programma. Secondo programma quando il blocco finally viene eseguito dopo che l'istruzione return viene eseguita e non si verifica alcuna eccezione perché dopo l'istruzione return eseguirà il compiler return nel metodo main e l'esecuzione rimanente non verrà eseguita nel blocco finally. Quindi l'eccezione non si verificherà.