精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java中的異常和處理,你知道多少?

開發(fā) 后端
程序運(yùn)行時(shí),發(fā)生的不被期望的事件,它阻止了程序按照程序員的預(yù)期正常執(zhí)行,這就是異常。異常發(fā)生時(shí),是任程序自生自滅,立刻退出終止,還是輸出錯(cuò)誤給用戶?或者用C語言風(fēng)格:用函數(shù)返回值作為執(zhí)行狀態(tài)。

Java中的異常和處理,你知道多少?

程序運(yùn)行時(shí),發(fā)生的不被期望的事件,它阻止了程序按照程序員的預(yù)期正常執(zhí)行,這就是異常。異常發(fā)生時(shí),是任程序自生自滅,立刻退出終止,還是輸出錯(cuò)誤給用戶?或者用C語言風(fēng)格:用函數(shù)返回值作為執(zhí)行狀態(tài)。

Java提供了更加優(yōu)秀的解決辦法:異常處理機(jī)制。

異常處理機(jī)制能讓程序在異常發(fā)生時(shí),按照代碼的預(yù)先設(shè)定的異常處理邏輯,針對(duì)性地處理異常,讓程序盡***可能恢復(fù)正常并繼續(xù)執(zhí)行,且保持代碼的清晰。

Java中的異??梢允呛瘮?shù)中的語句執(zhí)行時(shí)引發(fā)的,也可以是程序員通過throw 語句手動(dòng)拋出的,只要在Java程序中產(chǎn)生了異常,就會(huì)用一個(gè)對(duì)應(yīng)類型的異常對(duì)象來封裝異常,JRE就會(huì)試圖尋找異常處理程序來處理異常。

Throwable類是Java異常類型的頂層父類,一個(gè)對(duì)象只有是 Throwable 類的(直接或者間接)實(shí)例,他才是一個(gè)異常對(duì)象,才能被異常處理機(jī)制識(shí)別。JDK中內(nèi)建了一些常用的異常類,我們也可以自定義異常。

Java異常的分類和類結(jié)構(gòu)圖

Java標(biāo)準(zhǔn)褲內(nèi)建了一些通用的異常,這些類以Throwable為頂層父類。

Throwable又派生出Error類和Exception類。

錯(cuò)誤:Error類以及他的子類的實(shí)例,代表了JVM本身的錯(cuò)誤。錯(cuò)誤不能被程序員通過代碼處理,Error很少出現(xiàn)。因此,程序員應(yīng)該關(guān)注Exception為父類的分支下的各種異常類。

異常:Exception以及他的子類,代表程序運(yùn)行時(shí)發(fā)送的各種不期望發(fā)生的事件??梢员籎ava異常處理機(jī)制使用,是異常處理的核心。

 

總體上我們根據(jù)Javac對(duì)異常的處理要求,將異常類分為2類。

非檢查異常(unckecked exception):Error 和 RuntimeException 以及他們的子類。javac在編譯時(shí),不會(huì)提示和發(fā)現(xiàn)這樣的異常,不要求在程序處理這些異常。所以如果愿意,我們可以編寫代碼處理(使用try…catch…finally)這樣的異常,也可以不處理。對(duì)于這些異常,我們應(yīng)該修正代碼,而不是去通過異常處理器處理 。這樣的異常發(fā)生的原因多半是代碼寫的有問題。如除0錯(cuò)誤ArithmeticException,錯(cuò)誤的強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤ClassCastException,數(shù)組索引越界ArrayIndexOutOfBoundsException,使用了空對(duì)象NullPointerException等等。

檢查異常(checked exception):除了Error 和 RuntimeException的其它異常。javac強(qiáng)制要求程序員為這樣的異常做預(yù)備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會(huì)通過。這樣的異常一般是由程序的運(yùn)行環(huán)境導(dǎo)致的。因?yàn)槌绦蚩赡鼙贿\(yùn)行在各種未知的環(huán)境下,而程序員無法干預(yù)用戶如何使用他編寫的程序,于是程序員就應(yīng)該為這樣的異常時(shí)刻準(zhǔn)備著。如SQLException , IOException,ClassNotFoundException 等。

需要明確的是:檢查和非檢查是對(duì)于javac來說的,這樣就很好理解和區(qū)分了。

初識(shí)異常

下面的代碼會(huì)演示2個(gè)異常類型:ArithmeticException 和 InputMismatchException。前者由于整數(shù)除0引發(fā),后者是輸入的數(shù)據(jù)不能被轉(zhuǎn)換為int類型引發(fā)。

  1. package com.example; 
  2. import java. util .Scanner ; 
  3. public class AllDemo 
  4.       public static void main (String [] args ) 
  5.       { 
  6.             System . out. println( "----歡迎使用命令行除法計(jì)算器----" ) ; 
  7.             CMDCalculate (); 
  8.       } 
  9.       public static void CMDCalculate () 
  10.       { 
  11.             Scanner scan = new Scanner ( System. in ); 
  12.             int num1 = scan .nextInt () ; 
  13.             int num2 = scan .nextInt () ; 
  14.             int result = devide (num1 , num2 ) ; 
  15.             System . out. println( "result:" + result) ; 
  16.             scan .close () ; 
  17.       } 
  18.       public static int devide (int num1, int num2 ){ 
  19.             return num1 / num2 ; 
  20.       } 
  21. /***************************************** 
  22.   
  23. ----歡迎使用命令行除法計(jì)算器---- 
  24. Exception in thread "main" java.lang.ArithmeticException : / by zero 
  25.      at com.example.AllDemo.devide( AllDemo.java:30 ) 
  26.      at com.example.AllDemo.CMDCalculate( AllDemo.java:22 ) 
  27.      at com.example.AllDemo.main( AllDemo.java:12 ) 
  28.   
  29. ----歡迎使用命令行除法計(jì)算器---- 
  30. Exception in thread "main" java.util.InputMismatchException 
  31.      at java.util.Scanner.throwFor( Scanner.java:864 ) 
  32.      at java.util.Scanner.next( Scanner.java:1485 ) 
  33.      at java.util.Scanner.nextInt( Scanner.java:2117 ) 
  34.      at java.util.Scanner.nextInt( Scanner.java:2076 ) 
  35.      at com.example.AllDemo.CMDCalculate( AllDemo.java:20 ) 
  36.      at com.example.AllDemo.main( AllDemo.java:12 ) 
  37. *****************************************/  

異常是在執(zhí)行某個(gè)函數(shù)時(shí)引發(fā)的,而函數(shù)又是層級(jí)調(diào)用,形成調(diào)用棧的,因?yàn)?,只要一個(gè)函數(shù)發(fā)生了異常,那么他的所有的caller都會(huì)被異常影響。當(dāng)這些被影響的函數(shù)以異常信息輸出時(shí),就形成的了異常追蹤棧。

異常***發(fā)生的地方,叫做異常拋出點(diǎn)。

 

從上面的例子可以看出,當(dāng)devide函數(shù)發(fā)生除0異常時(shí),devide函數(shù)將拋出ArithmeticException異常,因此調(diào)用他的CMDCalculate函數(shù)也無法正常完成,因此也發(fā)送異常,而CMDCalculate的caller——main 因?yàn)镃MDCalculate拋出異常,也發(fā)生了異常,這樣一直向調(diào)用棧的棧底回溯。這種行為叫做異常的冒泡,異常的冒泡是為了在當(dāng)前發(fā)生異常的函數(shù)或者這個(gè)函數(shù)的caller中找到最近的異常處理程序。由于這個(gè)例子中沒有使用任何異常處理機(jī)制,因此異常最終由main函數(shù)拋給JRE,導(dǎo)致程序終止。

上面的代碼不使用異常處理機(jī)制,也可以順利編譯,因?yàn)?個(gè)異常都是非檢查異常。但是下面的例子就必須使用異常處理機(jī)制,因?yàn)楫惓J菣z查異常。

代碼中我選擇使用throws聲明異常,讓函數(shù)的調(diào)用者去處理可能發(fā)生的異常。但是為什么只throws了IOException呢?因?yàn)镕ileNotFoundException是IOException的子類,在處理范圍內(nèi)。

  1. @Test 
  2. public void testException() throws IOException 
  3.     //FileInputStream的構(gòu)造函數(shù)會(huì)拋出FileNotFoundException 
  4.     FileInputStream fileIn = new FileInputStream("E:\a.txt"); 
  5.       
  6.     int word; 
  7.     //read方法會(huì)拋出IOException 
  8.     while((word =  fileIn.read())!=-1)  
  9.     { 
  10.         System.out.print((char)word); 
  11.     } 
  12.     //close方法會(huì)拋出IOException 
  13.     fileIn.clos 
  14.  

異常處理的基本語法

在編寫代碼處理異常時(shí),對(duì)于檢查異常,有2種不同的處理方式:使用try…catch…finally語句塊處理它?;蛘?,在函數(shù)簽名中使用throws 聲明交給函數(shù)調(diào)用者caller去解決。

try…catch…finally語句塊

  1. try{ 
  2.      //try塊中放可能發(fā)生異常的代碼。 
  3.      //如果執(zhí)行完try且不發(fā)生異常,則接著去執(zhí)行finally塊和finally后面的代碼(如果有的話)。 
  4.      //如果發(fā)生異常,則嘗試去匹配catch塊。 
  5.   
  6. }catch(SQLException SQLexception){ 
  7.     //每一個(gè)catch塊用于捕獲并處理一個(gè)特定的異常,或者這異常類型的子類。Java7中可以將多個(gè)異常聲明在一個(gè)catch中。 
  8.     //catch后面的括號(hào)定義了異常類型和異常參數(shù)。如果異常與之匹配且是***匹配到的,則虛擬機(jī)將使用這個(gè)catch塊來處理異常。 
  9.     //在catch塊中可以使用這個(gè)塊的異常參數(shù)來獲取異常的相關(guān)信息。異常參數(shù)是這個(gè)catch塊中的局部變量,其它塊不能訪問。 
  10.     //如果當(dāng)前try塊中發(fā)生的異常在后續(xù)的所有catch中都沒捕獲到,則先去執(zhí)行finally,然后到這個(gè)函數(shù)的外部caller中去匹配異常處理器。 
  11.     //如果try中沒有發(fā)生異常,則所有的catch塊將被忽略。 
  12.   
  13. }catch(Exception exception){ 
  14.     //... 
  15. }finally{ 
  16.      
  17.     //finally塊通常是可選的。 
  18.    //無論異常是否發(fā)生,異常是否匹配被處理,finally都會(huì)執(zhí)行。 
  19.    //一個(gè)try至少要有一個(gè)catch塊,否則, 至少要有1個(gè)finally塊。但是finally不是用來處理異常的,finally不會(huì)捕獲異常。 
  20.   //finally主要做一些清理工作,如流的關(guān)閉,數(shù)據(jù)庫連接的關(guān)閉等。  
  21.  

需要注意的地方

1、try塊中的局部變量和catch塊中的局部變量(包括異常變量),以及finally中的局部變量,他們之間不可共享使用。

2、每一個(gè)catch塊用于處理一個(gè)異常。異常匹配是按照catch塊的順序從上往下尋找的,只有***個(gè)匹配的catch會(huì)得到執(zhí)行。匹配時(shí),不僅運(yùn)行精確匹配,也支持父類匹配,因此,如果同一個(gè)try塊下的多個(gè)catch異常類型有父子關(guān)系,應(yīng)該將子類異常放在前面,父類異常放在后面,這樣保證每個(gè)catch塊都有存在的意義。

3、java中,異常處理的任務(wù)就是將執(zhí)行控制流從異常發(fā)生的地方轉(zhuǎn)移到能夠處理這種異常的地方去。也就是說:當(dāng)一個(gè)函數(shù)的某條語句發(fā)生異常時(shí),這條語句的后面的語句不會(huì)再執(zhí)行,它失去了焦點(diǎn)。執(zhí)行流跳轉(zhuǎn)到最近的匹配的異常處理catch代碼塊去執(zhí)行,異常被處理完后,執(zhí)行流會(huì)接著在“處理了這個(gè)異常的catch代碼塊”后面接著執(zhí)行。

有的編程語言當(dāng)異常被處理后,控制流會(huì)恢復(fù)到異常拋出點(diǎn)接著執(zhí)行,這種策略叫做:resumption model of exception handling(恢復(fù)式異常處理模式 )

而Java則是讓執(zhí)行流恢復(fù)到處理了異常的catch塊后接著執(zhí)行,這種策略叫做:termination model of exception handling(終結(jié)式異常處理模式)

  1. public static void main(String[] args){ 
  2.         try { 
  3.             foo(); 
  4.         }catch(ArithmeticException ae) { 
  5.             System.out.println("處理異常"); 
  6.         } 
  7. public static void foo(){ 
  8.         int a = 5/0;  //異常拋出點(diǎn) 
  9.         System.out.println("為什么還不給我漲工資!!!");  //////////////////////不會(huì)執(zhí)行 
  10.  

throws 函數(shù)聲明

throws聲明:如果一個(gè)方法內(nèi)部的代碼會(huì)拋出檢查異常(checked exception),而方法自己又沒有完全處理掉,則javac保證你必須在方法的簽名上使用throws關(guān)鍵字聲明這些可能拋出的異常,否則編譯不通過。

throws是另一種處理異常的方式,它不同于try…catch…finally,throws僅僅是將函數(shù)中可能出現(xiàn)的異常向調(diào)用者聲明,而自己則不具體處理。

采取這種異常處理的原因可能是:方法本身不知道如何處理這樣的異常,或者說讓調(diào)用者處理更好,調(diào)用者需要為可能發(fā)生的異常負(fù)責(zé)。

  1. public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN 
  2. {  
  3.      //foo內(nèi)部可以拋出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 類的異常,或者他們的子類的異常對(duì)象。 

finally塊

finally塊不管異常是否發(fā)生,只要對(duì)應(yīng)的try執(zhí)行了,則它一定也執(zhí)行。只有一種方法讓finally塊不執(zhí)行:System.exit()。因此finally塊通常用來做資源釋放操作:關(guān)閉文件,關(guān)閉數(shù)據(jù)庫連接等等。

良好的編程習(xí)慣是:在try塊中打開資源,在finally塊中清理釋放這些資源。

需要注意的地方:

1、finally塊沒有處理異常的能力。處理異常的只能是catch塊。

2、在同一try…catch…finally塊中 ,如果try中拋出異常,且有匹配的catch塊,則先執(zhí)行catch塊,再執(zhí)行finally塊。如果沒有catch塊匹配,則先執(zhí)行finally,然后去外面的調(diào)用者中尋找合適的catch塊。

3、在同一try…catch…finally塊中 ,try發(fā)生異常,且匹配的catch塊中處理異常時(shí)也拋出異常,那么后面的finally也會(huì)執(zhí)行:首先執(zhí)行finally塊,然后去外圍調(diào)用者中尋找合適的catch塊。

這是正常的情況,但是也有特例。關(guān)于finally有很多惡心,偏、怪、難的問題,我在本文***統(tǒng)一介紹了,電梯速達(dá)->:finally塊和return

throw 異常拋出語句

throw exceptionObject

程序員也可以通過throw語句手動(dòng)顯式的拋出一個(gè)異常。throw語句的后面必須是一個(gè)異常對(duì)象。

throw 語句必須寫在函數(shù)中,執(zhí)行throw 語句的地方就是一個(gè)異常拋出點(diǎn),它和由JRE自動(dòng)形成的異常拋出點(diǎn)沒有任何差別。

  1. public void save(User user
  2.       if(user  == null)  
  3.           throw new IllegalArgumentException("User對(duì)象為空"); 
  4.       //...... 
  5.           
  6.  

異常的鏈化

在一些大型的,模塊化的軟件開發(fā)中,一旦一個(gè)地方發(fā)生異常,則如骨牌效應(yīng)一樣,將導(dǎo)致一連串的異常。假設(shè)B模塊完成自己的邏輯需要調(diào)用A模塊的方法,如果A模塊發(fā)生異常,則B也將不能完成而發(fā)生異常,但是B在拋出異常時(shí),會(huì)將A的異常信息掩蓋掉,這將使得異常的根源信息丟失。異常的鏈化可以將多個(gè)模塊的異常串聯(lián)起來,使得異常信息不會(huì)丟失。

異常鏈化:以一個(gè)異常對(duì)象為參數(shù)構(gòu)造新的異常對(duì)象。新的異對(duì)象將包含先前異常的信息。這項(xiàng)技術(shù)主要是異常類的一個(gè)帶Throwable參數(shù)的函數(shù)來實(shí)現(xiàn)的。這個(gè)當(dāng)做參數(shù)的異常,我們叫他根源異常(cause)。

查看Throwable類源碼,可以發(fā)現(xiàn)里面有一個(gè)Throwable字段cause,就是它保存了構(gòu)造時(shí)傳遞的根源異常參數(shù)。這種設(shè)計(jì)和鏈表的結(jié)點(diǎn)類設(shè)計(jì)如出一轍,因此形成鏈也是自然的了。

  1. public class Throwable implements Serializable { 
  2.     private Throwable cause = this; 
  3.      
  4.     public Throwable(String message, Throwable cause) { 
  5.         fillInStackTrace(); 
  6.         detailMessage = message; 
  7.         this.cause = cause; 
  8.     } 
  9.      public Throwable(Throwable cause) { 
  10.         fillInStackTrace(); 
  11.         detailMessage = (cause==null ? null : cause.toString()); 
  12.         this.cause = cause; 
  13.     } 
  14.       
  15.     //........ 
  16.  

下面是一個(gè)例子,演示了異常的鏈化:從命令行輸入2個(gè)int,將他們相加,輸出。輸入的數(shù)不是int,則導(dǎo)致getInputNumbers異常,從而導(dǎo)致add函數(shù)異常,則可以在add函數(shù)中拋出

一個(gè)鏈化的異常。

  1. public static void main(String[] args) 
  2.       
  3.     System.out.println("請(qǐng)輸入2個(gè)加數(shù)"); 
  4.     int result; 
  5.     try 
  6.     { 
  7.         result = add(); 
  8.         System.out.println("結(jié)果:"+result); 
  9.     } catch (Exception e){ 
  10.         e.printStackTrace(); 
  11.     } 
  12. //獲取輸入的2個(gè)整數(shù)返回 
  13. private static List<Integer> getInputNumbers() 
  14.     List<Integer> nums = new ArrayList<>(); 
  15.     Scanner scan = new Scanner(System.in); 
  16.     try { 
  17.         int num1 = scan.nextInt(); 
  18.         int num2 = scan.nextInt(); 
  19.         nums.add(new Integer(num1)); 
  20.         nums.add(new Integer(num2)); 
  21.     }catch(InputMismatchException immExp){ 
  22.         throw immExp; 
  23.     }finally { 
  24.         scan.close(); 
  25.     } 
  26.     return nums; 
  27.   
  28. //執(zhí)行加法計(jì)算 
  29. private static int add() throws Exception 
  30.     int result; 
  31.     try { 
  32.         List<Integer> nums =getInputNumbers(); 
  33.         result = nums.get(0)  + nums.get(1); 
  34.     }catch(InputMismatchException immExp){ 
  35.         throw new Exception("計(jì)算失敗",immExp);  /////////////////////////////鏈化:以一個(gè)異常對(duì)象為參數(shù)構(gòu)造新的異常對(duì)象。 
  36.     } 
  37.     return  result; 
  38.   
  39. /* 
  40. 請(qǐng)輸入2個(gè)加數(shù) 
  41. r 1 
  42. java.lang.Exception: 計(jì)算失敗 
  43.     at practise.ExceptionTest.add(ExceptionTest.java:53) 
  44.     at practise.ExceptionTest.main(ExceptionTest.java:18) 
  45. Caused by: java.util.InputMismatchException 
  46.     at java.util.Scanner.throwFor(Scanner.java:864) 
  47.     at java.util.Scanner.next(Scanner.java:1485) 
  48.     at java.util.Scanner.nextInt(Scanner.java:2117) 
  49.     at java.util.Scanner.nextInt(Scanner.java:2076) 
  50.     at practise.ExceptionTest.getInputNumbers(ExceptionTest.java:30) 
  51.     at practise.ExceptionTest.add(ExceptionTest.java:48) 
  52.     ... 1 more 
  53.   
  54. */ 

 

 

自定義異常

如果要自定義異常類,則擴(kuò)展Exception類即可,因此這樣的自定義異常都屬于檢查異常(checked exception)。如果要自定義非檢查異常,則擴(kuò)展自RuntimeException。

按照國際慣例,自定義的異常應(yīng)該總是包含如下的構(gòu)造函數(shù):

  • 一個(gè)無參構(gòu)造函數(shù)
  • 一個(gè)帶有String參數(shù)的構(gòu)造函數(shù),并傳遞給父類的構(gòu)造函數(shù)。
  • 一個(gè)帶有String參數(shù)和Throwable參數(shù),并都傳遞給父類構(gòu)造函數(shù)
  • 一個(gè)帶有Throwable 參數(shù)的構(gòu)造函數(shù),并傳遞給父類的構(gòu)造函數(shù)。

下面是IOException類的完整源代碼,可以借鑒。

  1. public class IOException extends Exception 
  2.     static final long serialVersionUID = 7818375828146090155L; 
  3.   
  4.     public IOException() 
  5.     { 
  6.         super(); 
  7.     } 
  8.   
  9.     public IOException(String message) 
  10.     { 
  11.         super(message); 
  12.     } 
  13.   
  14.     public IOException(String message, Throwable cause) 
  15.     { 
  16.         super(message, cause); 
  17.     } 
  18.   
  19.       
  20.     public IOException(Throwable cause) 
  21.     { 
  22.         super(cause); 
  23.     } 
  24.  

異常的注意事項(xiàng)

1、當(dāng)子類重寫父類的帶有 throws聲明的函數(shù)時(shí),其throws聲明的異常必須在父類異常的可控范圍內(nèi)——用于處理父類的throws方法的異常處理器,必須也適用于子類的這個(gè)帶throws方法 。這是為了支持多態(tài)。

例如,父類方法throws 的是2個(gè)異常,子類就不能throws 3個(gè)及以上的異常。父類throws IOException,子類就必須throws IOException或者IOException的子類。

至于為什么?我想,也許下面的例子可以說明。

  1. class Father 
  2.     public void start() throws IOException 
  3.     { 
  4.         throw new IOException(); 
  5.     } 
  6.   
  7. class Son extends Father 
  8.     public void start() throws Exception 
  9.     { 
  10.         throw new SQLException(); 
  11.     } 
  12. /**********************假設(shè)上面的代碼是允許的(實(shí)質(zhì)是錯(cuò)誤的)***********************/ 
  13. class Test 
  14.     public static void main(String[] args) 
  15.     { 
  16.         Father[] objs = new Father[2]; 
  17.         objs[0] = new Father(); 
  18.         objs[1] = new Son(); 
  19.   
  20.         for(Father obj:objs) 
  21.         { 
  22.         //因?yàn)镾on類拋出的實(shí)質(zhì)是SQLException,而IOException無法處理它。 
  23.         //那么這里的try。。catch就不能處理Son中的異常。 
  24.         //多態(tài)就不能實(shí)現(xiàn)了。 
  25.             try { 
  26.                  obj.start(); 
  27.             }catch(IOException) 
  28.             { 
  29.                  //處理IOException 
  30.             } 
  31.          } 
  32.    } 
  33.  

2、Java程序可以是多線程的。每一個(gè)線程都是一個(gè)獨(dú)立的執(zhí)行流,獨(dú)立的函數(shù)調(diào)用棧。如果程序只有一個(gè)線程,那么沒有被任何代碼處理的異常 會(huì)導(dǎo)致程序終止。如果是多線程的,那么沒有被任何代碼處理的異常僅僅會(huì)導(dǎo)致異常所在的線程結(jié)束。

也就是說,Java中的異常是線程獨(dú)立的,線程的問題應(yīng)該由線程自己來解決,而不要委托到外部,也不會(huì)直接影響到其它線程的執(zhí)行。

finally塊和return

首先一個(gè)不容易理解的事實(shí):在 try塊中即便有return,break,continue等改變執(zhí)行流的語句,finally也會(huì)執(zhí)行。

  1. public static void main(String[] args) 
  2.     int re = bar(); 
  3.     System.out.println(re); 
  4. private static int bar()  
  5.     try{ 
  6.         return 5; 
  7.     } finally{ 
  8.         System.out.println("finally"); 
  9.     } 
  10. /*輸出: 
  11. finally 
  12. */  

很多人面對(duì)這個(gè)問題時(shí),總是在歸納執(zhí)行的順序和規(guī)律,不過我覺得還是很難理解。我自己總結(jié)了一個(gè)方法。用如下GIF圖說明。

 

也就是說:try…catch…finally中的return 只要能執(zhí)行,就都執(zhí)行了,他們共同向同一個(gè)內(nèi)存地址(假設(shè)地址是0×80)寫入返回值,后執(zhí)行的將覆蓋先執(zhí)行的數(shù)據(jù),而真正被調(diào)用者取的返回值就是***一次寫入的。那么,按照這個(gè)思想,下面的這個(gè)例子也就不難理解了。

finally中的return 會(huì)覆蓋 try 或者catch中的返回值。

  1. public static void main(String[] args) 
  2.     { 
  3.         int result; 
  4.           
  5.         result  =  foo(); 
  6.         System.out.println(result);     /////////2 
  7.           
  8.         result = bar(); 
  9.         System.out.println(result);    /////////2 
  10.     } 
  11.   
  12.     @SuppressWarnings("finally"
  13.     public static int foo() 
  14.     { 
  15.         trz{ 
  16.             int a = 5 / 0; 
  17.         } catch (Exception e){ 
  18.             return 1; 
  19.         } finally{ 
  20.             return 2; 
  21.         } 
  22.   
  23.     } 
  24.   
  25.     @SuppressWarnings("finally"
  26.     public static int bar() 
  27.     { 
  28.         try { 
  29.             return 1; 
  30.         }finally { 
  31.             return 2; 
  32.         } 
  33.     } 

finally中的return會(huì)抑制(消滅)前面try或者catch塊中的異常

  1. class TestException 
  2.     public static void main(String[] args) 
  3.     { 
  4.         int result; 
  5.         try{ 
  6.             result = foo(); 
  7.             System.out.println(result);           //輸出100 
  8.         } catch (Exception e){ 
  9.             System.out.println(e.getMessage());    //沒有捕獲到異常 
  10.         } 
  11.           
  12.           
  13.         try{ 
  14.             result  = bar(); 
  15.             System.out.println(result);           //輸出100 
  16.         } catch (Exception e){ 
  17.             System.out.println(e.getMessage());    //沒有捕獲到異常 
  18.         } 
  19.     } 
  20.       
  21.     //catch中的異常被抑制 
  22.     @SuppressWarnings("finally"
  23.     public static int foo() throws Exception 
  24.     { 
  25.         try { 
  26.             int a = 5/0; 
  27.             return 1; 
  28.         }catch(ArithmeticException amExp) { 
  29.             throw new Exception("我將被忽略,因?yàn)橄旅娴膄inally中使用了return"); 
  30.         }finally { 
  31.             return 100; 
  32.         } 
  33.     } 
  34.       
  35.     //try中的異常被抑制 
  36.     @SuppressWarnings("finally"
  37.     public static int bar() throws Exception 
  38.     { 
  39.         try { 
  40.             int a = 5/0; 
  41.             return 1; 
  42.         }finally { 
  43.             return 100; 
  44.         } 
  45.     } 

finally中的異常會(huì)覆蓋(消滅)前面try或者catch中的異常

  1. class TestException 
  2.     public static void main(String[] args) 
  3.     { 
  4.         int result; 
  5.         try{ 
  6.             result = foo(); 
  7.         } catch (Exception e){ 
  8.             System.out.println(e.getMessage());    //輸出:我是finaly中的Exception 
  9.         } 
  10.           
  11.           
  12.         try{ 
  13.             result  = bar(); 
  14.         } catch (Exception e){ 
  15.             System.out.println(e.getMessage());    //輸出:我是finaly中的Exception 
  16.         } 
  17.     } 
  18.       
  19.     //catch中的異常被抑制 
  20.     @SuppressWarnings("finally"
  21.     public static int foo() throws Exception 
  22.     { 
  23.         try { 
  24.             int a = 5/0; 
  25.             return 1; 
  26.         }catch(ArithmeticException amExp) { 
  27.             throw new Exception("我將被忽略,因?yàn)橄旅娴膄inally中拋出了新的異常"); 
  28.         }finally { 
  29.             throw new Exception("我是finaly中的Exception"); 
  30.         } 
  31.     } 
  32.       
  33.     //try中的異常被抑制 
  34.     @SuppressWarnings("finally"
  35.     public static int bar() throws Exception 
  36.     { 
  37.         try { 
  38.             int a = 5/0; 
  39.             return 1; 
  40.         }finally { 
  41.             throw new Exception("我是finaly中的Exception"); 
  42.         } 
  43.           
  44.     } 
  45.  

上面的3個(gè)例子都異于常人的編碼思維,因此我建議:

  • 不要在fianlly中使用return。
  • 不要在finally中拋出異常。
  • 減輕finally的任務(wù),不要在finally中做一些其它的事情,finally塊僅僅用來釋放資源是最合適的。
  • 將盡量將所有的return寫在函數(shù)的***面,而不是try … catch … finally中。 
責(zé)任編輯:龐桂玉 來源: 計(jì)算機(jī)與網(wǎng)絡(luò)安全
相關(guān)推薦

2019-10-28 09:53:42

Java開發(fā)結(jié)構(gòu)

2023-09-18 08:56:57

StringJava

2025-01-22 00:00:00

異常catch編程

2021-07-26 23:57:48

Vuex模塊項(xiàng)目

2023-01-16 08:09:51

SpringMVC句柄

2022-08-11 08:46:23

索引數(shù)據(jù)結(jié)構(gòu)

2024-10-08 08:00:00

2024-05-06 00:30:00

MVCC數(shù)據(jù)庫

2021-11-01 08:00:00

Java異常處理開發(fā)

2019-05-08 16:00:48

人工智能人臉識(shí)別刷臉

2018-01-02 09:31:12

大數(shù)據(jù)數(shù)據(jù)互聯(lián)網(wǎng)

2023-08-28 07:39:49

線程調(diào)度基本單位

2023-12-11 14:19:00

Java程序異常

2024-04-16 16:20:46

2025-06-12 03:55:00

項(xiàng)目處理異常代碼

2022-03-23 15:36:13

數(shù)字化轉(zhuǎn)型數(shù)據(jù)治理企業(yè)

2023-08-02 08:14:33

監(jiān)控MTS性能

2019-07-17 05:50:13

ava異常編譯器

2018-08-24 06:56:17

2011-06-24 17:30:34

網(wǎng)站權(quán)重
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

特级黄色片视频| 日本免费一区二区三区| 久久精品99久久久久久| 果冻天美麻豆一区二区国产| 黄色成人在线播放| 日韩午夜视频在线观看| 国产精品久久久久久免费播放| 围产精品久久久久久久| 欧美精品一区二区三区在线播放| 97视频在线免费播放| jizzjizz在线观看| 国产伦理精品不卡| 日本三级韩国三级久久| 久久国产波多野结衣| 久久婷婷国产| 欧美日韩电影一区| 国自产拍偷拍精品啪啪一区二区| 福利在线视频导航| 国产河南妇女毛片精品久久久| 97国产在线视频| 少妇视频一区二区| 一区二区三区四区在线看| 7777精品伊人久久久大香线蕉完整版 | 中文字幕欧美色图| 国产一区日韩一区| 亚洲欧美激情四射在线日| 一级 黄 色 片一| 欧美gay视频| 亚洲午夜免费福利视频| 亚洲欧洲日夜超级视频| 亚洲人视频在线观看| 激情欧美日韩一区二区| 国产97色在线| 日韩av电影网址| 忘忧草精品久久久久久久高清| 亚洲欧美一区二区三区情侣bbw| av在线免费观看不卡| 成人免费毛片嘿嘿连载视频…| 亚洲成人手机在线| 樱空桃在线播放| 98在线视频| 国产亚洲制服色| 91久久精品一区二区别| 伊人久久一区二区| 丝袜美腿亚洲综合| 88国产精品欧美一区二区三区| 青青草国产在线观看| 久久在线播放| 在线视频欧美日韩精品| 亚洲一区二区观看| 国产欧美自拍一区| 日韩免费一区二区三区在线播放| 日本人69视频| 国产91欧美| 欧美性猛交一区二区三区精品| 欧美日韩在线中文| 水蜜桃在线视频| 性做久久久久久免费观看| 日韩精品一区二区在线视频| 国产乱色在线观看| 日韩理论片在线| av不卡在线免费观看| 五月香视频在线观看| 国产精品天美传媒| 亚洲激情一区二区三区| www.久久热.com| 国产精品无码永久免费888| 日韩一区二区电影在线观看| 第一页在线观看| 日本一区二区视频在线观看| 日韩啊v在线| 成人免费高清在线播放| 国产精品无遮挡| 一区二区三区四区免费视频| 米奇精品一区二区三区| 亚洲免费视频成人| 人人妻人人澡人人爽欧美一区双| 国产丝袜视频在线播放| 午夜激情一区二区| 久久久噜噜噜www成人网| 最新欧美电影| 欧美精品三级在线观看| 久久人人爽人人片| 福利片在线一区二区| 日韩精品中文字幕在线播放| 91视频免费观看网站| 久久亚洲成人| 欧美激情国内偷拍| 欧美h在线观看| 日本不卡123| 亚洲最大成人网色| 午夜一区在线观看| 日本一区二区三区dvd视频在线| 亚洲三区在线| 欧洲成人综合网| 狠狠躁18三区二区一区| www午夜视频| 香港久久久电影| 精品调教chinesegay| ass极品国模人体欣赏| 欧美精品不卡| 青青草成人在线| 亚洲一区二区视频在线播放| 福利一区福利二区| 日韩免费电影一区二区三区| 羞羞视频在线观看不卡| 岛国av一区二区在线在线观看| 麻豆一区二区三区视频| 高潮按摩久久久久久av免费| 亚洲一区www| 久久中文字幕在线观看| 日本午夜精品一区二区三区电影| 亚洲在线www| 狠狠狠综合7777久夜色撩人| 亚洲精品视频在线观看网站| 久久久久久久少妇| 一区二区三区免费在线看| 在线播放日韩精品| 成人精品在线看| 国产成人在线视频网址| 亚洲欧美综合一区| 日韩脚交footjobhdboots| 666欧美在线视频| 成人免费无遮挡无码黄漫视频| 中文字幕人成人乱码| 国产精品青青在线观看爽香蕉| 色一情一乱一乱一区91av| 国产精品国产自产拍在线| 鲁一鲁一鲁一鲁一澡| 亚洲精品在线播放| 色噜噜亚洲精品中文字幕| 免费黄色网址在线| 成人av资源在线观看| 中文字幕不卡每日更新1区2区| 韩漫成人漫画| 亚洲福利在线观看| 欧美黑人精品一区二区不卡| 久久国产免费看| 日韩欧美在线电影| av高清不卡| 亚洲加勒比久久88色综合| 久草视频在线资源站| 国产中文字幕一区| 影音先锋欧美资源| 国产精品伦一区二区| 亚洲天堂av图片| 黄色片网站在线免费观看| 99久久亚洲一区二区三区青草| 欧美做暖暖视频| 99久久99九九99九九九| 日韩专区在线播放| 中文字幕一区二区三区人妻四季 | 国产精品男人的天堂| 色就是色亚洲色图| 欧美日韩一区二区精品| 50一60岁老妇女毛片| 在线观看亚洲| 国产青春久久久国产毛片| 17videosex性欧美| 亚洲电影中文字幕| 亚洲精品国产精品乱码| 99久久99久久久精品齐齐| www.99热这里只有精品| 欧美人妖视频| 热re91久久精品国99热蜜臀| 欧美婷婷久久五月精品三区| 一本一道综合狠狠老| 88久久精品无码一区二区毛片| 久久精品123| 日本一区免费| 日韩伦理一区二区| 久久亚洲精品一区| 免费看国产片在线观看| 精品成人av一区| 超碰97人人干| 日韩av一级电影| 一本久道久久综合狠狠爱亚洲精品| 99久久er| 九九精品视频在线| 天堂网在线中文| 日本久久精品电影| 国精品人伦一区二区三区蜜桃| 国产一区二区三区国产| 欧美一级视频在线播放| 亚洲欧美日本伦理| 国产三级精品网站| 福利网站在线观看| 亚洲视频在线免费观看| 国产日产亚洲系列最新| 午夜欧美大尺度福利影院在线看| www.中文字幕av| 久久精品国产99| 国产aaa免费视频| 国产区精品区| 亚洲专区国产精品| 韩国主播福利视频一区二区三区| 久久精品国产亚洲精品2020| 日韩一级免费视频| 欧美日韩国产小视频在线观看| 免费三片在线播放| 国产性做久久久久久| 成人高清在线观看视频| 亚洲黄网站黄| 亚洲最新在线| 欧美精品国产白浆久久久久| 国产精品视频在线观看| 丰满的护士2在线观看高清| 国产亚洲一区二区在线| 亚洲a视频在线观看| 日本韩国精品一区二区在线观看| 国产免费无码一区二区视频| 久久免费的精品国产v∧| 爱情岛论坛亚洲自拍| 久久久精品性| 欧美大黑帍在线播放| 成人情趣视频网站| 国产亚洲精品自在久久| 电影91久久久| 国产精品99久久久久久白浆小说| 天堂av中文在线| 在线视频亚洲欧美| 色综合888| 日韩欧美国产综合| 亚洲天堂中文在线| 色天使久久综合网天天| 日本亚洲色大成网站www久久| 中文字幕中文字幕在线一区 | 97久久综合精品久久久综合| 国产精品丝袜久久久久久不卡| 国产伦理精品| 久久91亚洲人成电影网站| 日韩子在线观看| 亚洲精选一区二区| 人人妻人人玩人人澡人人爽| 777xxx欧美| 91亚洲精品国偷拍自产在线观看| 色综合天天视频在线观看| 日韩av在线播| 亚洲综合一区二区精品导航| 成人做爰视频网站| 国产精品美日韩| 欧美成人国产精品一区二区| 91在线视频播放地址| 人妻 日韩 欧美 综合 制服| 国产精品自拍三区| 精产国品一二三区| 激情亚洲综合在线| 香蕉视频999| 久久狠狠亚洲综合| 亚洲精品视频三区| 久久99国产乱子伦精品免费| av网站在线不卡| 日本美女视频一区二区| 天天操天天爽天天射| 久久天堂精品| 欧美激情精品久久久久久小说| 国产美女诱惑一区二区| 日本免费黄视频| 性欧美暴力猛交另类hd| jizzjizzxxxx| 久久这里有精品15一区二区三区| www.com毛片| 午夜综合激情| 激情视频综合网| 日本不卡的三区四区五区| 九色porny自拍| 国精产品一区一区三区mba视频| 在线免费看v片| 国产激情精品久久久第一区二区| 精品人妻无码中文字幕18禁| 丁香婷婷综合激情五月色| 91人人澡人人爽| 99久久久精品| 免费一级做a爰片久久毛片潮| 久久久噜噜噜久噜久久综合| 国产黄色大片免费看| 国产精品久久夜| 亚洲波多野结衣| 亚洲夂夂婷婷色拍ww47| 亚洲天堂一区在线| 欧美三级视频在线| av网站在线观看免费| 亚洲国产精品久久精品怡红院| 久香视频在线观看| 日韩视频欧美视频| 国产天堂在线播放视频| 日韩免费av在线| **日韩最新| 国产偷国产偷亚洲高清97cao| 久久av资源| 中文字幕一区二区三区四区五区人 | 中文字幕人妻无码系列第三区| 国产99精品视频| 亚洲观看黄色网| 国产精品视频线看| 九九九国产视频| 在线观看视频欧美| 国产高清免费av| 亚洲性xxxx| 中文字幕伦理免费在线视频 | 久久久精品性| 成人免费播放视频| 国产亚洲欧美色| 免费人成年激情视频在线观看| 岛国av一区二区在线在线观看| 亚洲一级在线播放| 亚洲激情视频在线观看| 欧美成人二区| 国产91精品黑色丝袜高跟鞋| 亚洲欧美在线综合| 欧美亚洲另类在线一区二区三区 | 一区二区三区视频在线 | 欧美在线中文字幕| 精品中文字幕一区二区三区四区| 欧美成人免费在线| 欧美午夜久久| 国产乱女淫av麻豆国产| 99视频精品全部免费在线| 免费看一级黄色| 日韩欧美福利视频| 亚洲欧美激情另类| 日韩视频在线免费观看| 三级成人黄色影院| 国产日韩一区欧美| 在线一区免费| 色哟哟精品视频| 99在线精品一区二区三区| 亚洲色图综合区| 91久久精品一区二区三| 日本美女一级片| 久久99久久99精品中文字幕| 91综合国产| 欧美一区二区三区在线免费观看| 国内久久视频| 色婷婷一区二区三区在线观看| 国产拍欧美日韩视频二区| 国产精品久久久久久久妇| 日韩精品最新网址| 中文字幕伦理免费在线视频| 成人激情视频在线| 久久精品av| 亚洲一级免费观看| 国产三级一区二区三区| av中文在线播放| 亚洲国产欧美精品| 国产美女一区视频| 97人人模人人爽视频一区二区| 香蕉视频国产精品 | 久久高清无码视频| 欧美一卡二卡三卡| av网址在线播放| 91精品视频在线免费观看| 国产精品国产一区| 亚洲精品免费一区亚洲精品免费精品一区| 国产欧美一区二区三区鸳鸯浴| 中文字幕国产在线观看| 亚洲跨种族黑人xxx| 日韩欧美精品一区二区三区| 精品视频在线观看| 亚洲欧美日韩在线观看a三区| 97人妻精品一区二区免费| 色婷婷综合在线| 都市激情一区| 成人av在线亚洲| 亚洲乱码精品| 中文字幕第三区| 亚洲午夜电影在线观看| 特黄aaaaaaaaa真人毛片| 欧洲s码亚洲m码精品一区| 国产日产一区| 狠狠躁狠狠躁视频专区| 国产精品乱码一区二三区小蝌蚪| 国产又黄又大又爽| 九九久久综合网站| 欧美电影在线观看免费| 爱福利视频一区二区| 亚洲国产精品精华液2区45| 国产乱淫av免费| 久久久久久国产精品| 日韩极品少妇| 激情视频免费网站| 亚洲女同ⅹxx女同tv| 全部免费毛片在线播放一个| 国产99在线|中文| 日韩中文字幕高清在线观看| 亚洲第一天堂久久| 午夜视频一区二区| 福利在线午夜| 国产69精品久久久久9999apgf| 国产精品夜夜夜| 国产第一页精品| 日韩精品中文字幕一区| 免费h视频在线观看| 亚洲aⅴ天堂av在线电影软件| 国产成人精品影视| 亚洲欧美一二三区| 九色精品美女在线| 欧美精品一区二区久久| 4438x全国最大成人| 91黄色在线观看|