2015-10-13 55 views
18

我有一個程序如下:的try /終於沒有漁獲物和返回值

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

上面的程序運行後,下面的結果在控制檯中看到:

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

這種現象是正常的,因爲拋出異常以主要方法。

然後我改變代碼如下:

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

當上面的程序運行,我看到控制檯以下結果:

finally 
after call , res = 20 

我的問題涉及到第二格式。爲什麼當finally塊返回時,異常不會拋出到main方法?

+2

@Tunaki不是。 –

+1

這可能是:http://stackoverflow.com/q/48088/1743880? – Tunaki

+0

請看看:http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java – Rehman

回答

7

JLS(重點煤礦):

如果try塊的執行突然結束,因爲 一個值V拋,然後有一個選擇:
[...]
如果V的運行時類型與try語句的任何catch子句的可捕獲異常類不是兼容的,則執行finally 塊。然後有一個選擇:

  • 如果finally塊正常完成,那麼如果finally塊的原因小號突然完成了try語句完成突然,因爲該值V.

  • 的拋,那麼由於原因S(和值V的投擲是 被丟棄並被遺忘),try語句突然完成。

TL/DR
這意味着如果returnfinally塊內未拋出異常的方法的回報。
/TL/DR

此外return,還有其他statementes可導致finally完整突然和忘記例外。它們在JLS Section 14.1中定義。基本上,它是break,continue,return或一個異常(拋出或由聲明/方法引起)。這個完整的try/catch/finally塊完成這個原因。

try/catch/finally的規範中還有一些情況,尤其是在沒有異常或匹配的catch子句存在的情況下。這歸結於finally節拍catch節拍try

3
  1. 如果在finally部分中使用return,則會失去例外。方法將以正常類型的返回值結束。
  2. 如果您在finally部分中未使用return,則在您的情況下,方法將以例外結束。

第一種情況:

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

第二種情況:

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

第三種情況:

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

注意:使用finally節引發異常或返回值是一種不好的做法。例如,創建此部分用於關閉外部資源。

0

Java的return並不總是返回,this可能會招待。

13

當你拋出異常時,它將首先通過finally塊。

如果您的finally塊沒有返回或拋出任何東西,則會傳遞原始異常。

如果另一方面finally塊返回一個值,則該異常根本不再傳播。

2

在finally塊一切都拋出的異常之前執行,所以如果你在finally塊返回時,異常不會在所有拋出。出於這個原因,從finally塊返回通常是一個壞主意。

查看this blog瞭解關於此的一些信息。

8

最後看看try catch的執行情況。

java language specification -jls-14.20.2

如果V的運行時類型不是分配與可捕獲的異常類try語句中的任何catch子句的兼容,那麼finally塊被執行。然後有一個選擇:

如果finally塊正常完成,則try語句突然結束,因爲該值V.

如果投擲finally塊突然結束的原因S,則try語句由於原因S突然完成(並丟棄值V的投擲並忘記)。

+1

只是想知道,S是什麼原因? – bvdb

+1

@bvdb在這種情況下,異常。 –

+1

@bvdb JLS 14.1:https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html;馬虎說:它可以是任何停止塊結束在其結束括號的語句:「break」,「continue」,「return」或異常。 – flo

0

statementin finally塊已基本停止 除了在try塊發生從向上傳播,甚至 雖然它沒有被捕獲的回報。

但是,在編寫這段代碼時,Java編譯器確實會通知警告。 雖然return statements應始終處於try block,並finally塊uasully爲releasing/closing connections, pointers etc.

看起來是那樣的Java的行爲。

看一看here

0

如果你讀的最後,然後它說Java文檔,

它允許程序員避免不慎被返回繞過其清除代碼,繼續,或斷裂。清理代碼放在finally塊中總是一個很好的做法,即使沒有預期的例外情況。

所以,如果你把清理代碼放在finally塊之後,如果有異常,它將不會被調用。

0

在第一種情況下,finally塊作爲其行爲執行,但未捕獲異常,但通過main方法拋出異常。通過這個例子

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

檢查它在上面的代碼,Main Catch執行的原因。

在第二種情況下,您返回了該號碼,因此主方法中沒有出現異常。

0

因爲finally塊總是執行,異常是否發生與否,和如果從最終手段,您發送您的執行調用方法和返回你失去了異常。所以它也會產生警告。

enter image description here

0

在第一個程序時ArithmeticException發生在try塊,然後調用finally塊,執行finally塊,異常發生後。因爲異常不是由程序處理的。 第二個程序在finally語句執行之後finally語句執行時沒有發生異常,因爲return語句之後執行main方法中的編譯器返回,而剩餘的執行在finally語句塊中不會執行。所以異常不會發生。