2015-10-13 9 views
18

Mam program w następujący sposób:try/finally bez połowu i powrotnej wartości

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") ; 
     } 
    } 
} 

po biegu powyższego programu, następujący wynik widział w konsoli:

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

to zachowanie jest normalne, bo wyjątek rzucony do głównej metody.

Potem zmienić kod w następujący sposób:

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; 
     } 
    } 
} 

Po uruchomieniu powyższego programu Widziałem następujący wynik w konsoli:

finally 
after call , res = 20 

Moje pytanie związane z drugim formatem. Dlaczego po powrocie w końcu bloku, wyjątek nie rzucony do głównej metody?

+2

@Tunaki Nie to. –

+1

Ten może: http://stackoverflow.com/q/48088/1743880? – Tunaki

+0

Proszę spojrzeć: http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java – Rehman

Odpowiedz

7

Z JLS kopalni (nacisk):

Jeżeli wykonanie bloku try kończy się nagle z powodu rzutu wartość V, po czym istnieje możliwość wyboru:
[...]
Jeśli typem czasu wykonywania V nie jest przypisanie zgodne z klasą wyjątków możliwą do odłowu dla dowolnej klauzuli catch instrukcji try, wówczas wykonywany jest ostatecznie blok . Wtedy istnieje możliwość wyboru:

  • Jeżeli wreszcie blok kończy się normalnie, wtedy instrukcja try kończy się nagle z powodu rzutu wartości V.

  • Jeżeli wreszcie blok kończy się nagle z przyczyn S, następnie instrukcja try kończy się nagle z powodu S (, a rzut wartości V jest odrzucony i zapomniany).

TL/DR
Oznacza to, że jeśli return w bloku finally powraca metoda nie powoduje wyjątku.
/TL/DR

Poza return, istnieją inne, które mogą powodować statementes blok finally do kompletnego nagle i zapomnieć o wyjątku. Są one zdefiniowane w JLS Section 14.1. Zasadniczo jest to break, continue, return lub wyjątek (wyrzucony lub spowodowany przez instrukcję/metodę). Kompletny blok try/catch/finally kończy się z tego powodu.

Jest kilka innych przypadków w specyfikacji try/catch/finally, zwłaszcza jeśli nie ma wyjątków lub istnieje zgodna klauzula catch. Sprowadza się do finally bije catch bije try.

3
  1. Jeśli użyjesz return w sekcji , stracisz wyjątek. Metoda zostanie zakończona normalnym typem wartości zwracanej.
  2. Jeśli nie używasz return w sekcji finally, w twoim przypadku metoda zostanie zakończona wyjątkiem.

Pierwszy przypadek:

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

Drugi przypadek:

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

Trzeci przypadek:

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

Uwaga: Używanie sekcji do zgłaszania wyjątków lub zwracania wartości jest złym zwyczajem. Ta sekcja została utworzona, na przykład, do zamykania zasobów zewnętrznych.

0

Java's return nie zawsze wraca, this może zabawiać.

13

Po zgłoszeniu wyjątku, najpierw przejdzie przez twój blok finally.

Jeśli twój blok finally nie zwraca ani nie rzuca niczego, to oryginalny wyjątek jest przekazywany.

Jeśli twój blok z drugiej strony zwraca wartość, to wyjątek nie jest już w ogóle propagowany.

2

Wszystko w bloku finally jest wykonywany zanim zostanie wyjątek, więc jeśli wrócimy w bloku finally, wyjątek nie zostanie rzucony w ogóle. Z tego powodu generalnie złym pomysłem jest powrót z bloku końcowego.

Proszę spojrzeć na this blog, aby uzyskać informacje na ten temat.

8

Spójrz na wykonanie spróbuj catch wreszcie.

Od java language specification -jls-14.20.2

Jeśli typ run-time V nie jest przyporządkowanie kompatybilny z połów klasy wyjątkiem klauzuli catch w instrukcji try, wtedy wreszcie blok jest wykonywany. Wtedy istnieje możliwość wyboru:

Jeżeli wreszcie blok kończy się normalnie, wtedy instrukcja try kończy się nagle z powodu rzutu wartości V.

Jeżeli wreszcie blok kończy się nagle z przyczyn S, wówczas instrukcja try kończy się nagle z powodu S (, a rzut wartości V zostaje odrzucony i zapomniany).

+1

Zastanawiasz się, jaki jest powód S? – bvdb

+1

@bvdb W tym przypadku wyjątek. –

+1

@bvdb JLS 14.1: https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html; Sloppy powiedział: Może to być dowolna instrukcja, która zatrzymuje blok kończący się na nawiasie kończącym: 'break',' continue', 'return' lub exception. – flo

0

Zwrot statementin na końcu bloku w zasadzie zatrzymania w wyjątkiem, że wydarzyło się w bloku try od rozmnożeniowego się nawet choć nie został złapany.

Ale kompilator Java powiadamia ostrzeżenia podczas pisania tego fragmentu kodu. Choć return statements zawsze powinna leżeć w try block i finally blok jest uasully dla releasing/closing connections, pointers etc.

Wydaje drogę Java zachowuje.

spojrzeć here

0

Jeśli czytasz java DOC wreszcie to mówi

pozwala programiście, aby uniknąć konieczności kodu oczyszczania przypadkowo zablokowanych przez powrót, kontynuować lub złamać. Umieszczenie kodu porządkowego w bloku finally jest zawsze dobrą praktyką, nawet jeśli nie przewiduje się wyjątków.

Więc jeśli wstawisz kod czyszczenia po bloku finally, nie zostanie on wywołany, jeśli wystąpi wyjątek.

0

W pierwszym przypadku ostatni blok jest wykonywany jako jego zachowanie, ale nie przechwycił wyjątku, ale wyjątek jest generowany główną metodą. Sprawdź to za pomocą tego przykładu

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") ; 
     } 
    } 
} 

W powyższym kodzie, Main Catch został wykonany.

W drugim przypadku zwrócono numer, więc nie było żadnego wyjątku w głównej metodzie.

0

Ponieważ końcu bloku jest zawsze wykonywany, czy wyjątek występuje, czy nie, i jeśli wrócisz z ostatecznie środki, wysyłasz swoje wykonanie metody wywołującej i tracisz wyjątek. Więc generuje również ostrzeżenie.

enter image description here

0

W pierwszym programie, gdy ArithmeticException wystąpić w bloku try następnie wywołać w końcu zablokować i po wykonanie bloku finally, wyjątek występuje. ponieważ wyjątek nie jest obsługiwany przez program. Drugi program, gdy ostatecznie blok zostanie wykonany po wykonaniu instrukcji return i nie pojawi się żaden wyjątek, ponieważ po instrukcji return wykonaj return kompilatora w metodzie głównej, a pozostałe wykonanie nie zostanie wykonane w bloku finally. Tak więc wyjątek się nie pojawi.

Powiązane problemy