Groovy 異常處理

2023-01-04 09:02 更新

任何編程語言都需要異常處理來處理運(yùn)行時(shí)錯(cuò)誤,從而可以保持應(yīng)用程序的正常流程。

異常通常會(huì)破壞應(yīng)用程序的正常流程,這就是為什么我們需要在我們的應(yīng)用程序中使用異常處理的原因。

例如大致分為以下類別 -

  • 檢測(cè)異常 -擴(kuò)展Throwable類(除了RuntimeException和Error)的類稱為檢查異常egIOException,SQLException等。檢查的異常在編譯時(shí)檢查。

一個(gè)典型的情況是FileNotFoundException。假設(shè)您的應(yīng)用程序中有以下代碼,它從E盤中的文件讀取。

class Example {
   static void main(String[] args) {
      File file = new File("E://file.txt");
      FileReader fr = new FileReader(file);
   } 
}

如果文件(file.txt)不在E盤中,那么將引發(fā)以下異常。

抓?。簀ava.io.FileNotFoundException:E:\ file.txt(系統(tǒng)找不到指定的文件)。

java.io.FileNotFoundException:E:\ file.txt(系統(tǒng)找不到指定的文件)。

  • 未經(jīng)檢查的異常 -擴(kuò)展RuntimeException的類稱為未檢查異常,例如,ArithmeticException,NullPointerException,ArrayIndexOutOfBoundsException等。未檢查的異常在編譯期不檢查,而是在運(yùn)行時(shí)檢查。

一個(gè)典型的情況是ArrayIndexOutOfBoundsException,當(dāng)您嘗試訪問大于數(shù)組長度的數(shù)組的索引時(shí),會(huì)發(fā)生這種情況。以下是這種錯(cuò)誤的典型例子。

class Example {
   static void main(String[] args) {
      def arr = new int[3];
      arr[5] = 5;
   } 
}

當(dāng)上面的代碼執(zhí)行時(shí),將引發(fā)以下異常。

抓取:java.lang.ArrayIndexOutOfBoundsException:5

java.lang.ArrayIndexOutOfBoundsException:5

  • 錯(cuò)誤 -錯(cuò)誤無法恢復(fù)。 OutOfMemoryError,VirtualMachineError,AssertionError等。

這些是程序永遠(yuǎn)不能恢復(fù)的錯(cuò)誤,將導(dǎo)致程序崩潰。

下圖顯示了如何組織Groovy中的異常層次結(jié)構(gòu)。它都基于Java中定義的層次結(jié)構(gòu)。

層次結(jié)構(gòu)異常

捕捉異常

方法使用try和catch關(guān)鍵字的組合捕獲異常。 try / catch塊放置在可能生成異常的代碼周圍。

try { 
   //Protected code 
} catch(ExceptionName e1) {
   //Catch block 
}

所有可能引發(fā)異常的代碼都放在受保護(hù)的代碼塊中。

在catch塊中,您可以編寫自定義代碼來處理異常,以便應(yīng)用程序可以從異常中恢復(fù)。

讓我們看一個(gè)類似的代碼示例,我們?cè)谏厦婵吹揭粋€(gè)索引值大于數(shù)組大小的數(shù)組。但這次讓我們將我們的代碼包裝在try / catch塊中。

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   }
}

當(dāng)我們運(yùn)行上面的程序,我們將得到以下結(jié)果 -

Catching the exception 
Let's move on after the exception

從上面的代碼,我們?cè)趖ry塊中包裝錯(cuò)誤的代碼。在catch塊中,我們只是捕獲我們的異常并輸出一個(gè)異常已經(jīng)發(fā)生的消息。

多個(gè)捕獲塊

可以有多個(gè)catch塊來處理多種類型的異常。對(duì)于每個(gè)catch塊,根據(jù)引發(fā)的異常的類型,您將編寫代碼來相應(yīng)地處理它。

讓我們修改上面的代碼來具體捕捉ArrayIndexOutOfBoundsException。以下是代碼段。

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   } 
}

當(dāng)我們運(yùn)行上面的程序,我們將得到以下結(jié)果 -

Catching the Aray out of Bounds exception 
Let's move on after the exception

從上面的代碼,你可以看到ArrayIndexOutOfBoundsException catch塊首先被捕獲,因?yàn)樗馕吨惓5臉?biāo)準(zhǔn)。

finally塊

finally塊跟在try塊或catch塊之后。代碼的finally塊總是執(zhí)行,而不管異常的發(fā)生。

使用finally塊可以運(yùn)行任何你想要執(zhí)行的清除類型語句,無論在受保護(hù)代碼中發(fā)生什么。該塊的語法如下。

try { 
   //Protected code 
} catch(ExceptionType1 e1) { 
   //Catch block 
} catch(ExceptionType2 e2) { 
   //Catch block 
} catch(ExceptionType3 e3) { 
   //Catch block 
} finally {
   //The finally block always executes. 
}

讓我們修改我們上面的代碼并添加finally代碼塊。以下是代碼段。

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      } finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
} 

當(dāng)我們運(yùn)行上面的程序,我們將得到以下結(jié)果 -

Catching the Array out of Bounds exception 
The final block 
Let's move on after the exception

以下是Groovy中提供的異常方法 -

public String getMessage()

返回有關(guān)已發(fā)生異常的詳細(xì)消息。此消息在Throwable構(gòu)造函數(shù)中初始化。

public Throwable getCause()

返回由Throwable對(duì)象表示的異常原因。

public String toString()

返回與getMessage()的結(jié)果連接的類的名稱。

public void printStackTrace()

將toString()的結(jié)果與堆棧跟蹤一起打印到System.err,錯(cuò)誤輸出流。

public StackTraceElement [] getStackTrace()

返回包含堆棧跟蹤上的每個(gè)元素的數(shù)組。索引0處的元素表示調(diào)用堆棧的頂部,數(shù)組中的最后一個(gè)元素表示調(diào)用堆棧底部的方法。

public Throwable fillInStackTrace()

使用當(dāng)前堆棧跟蹤填充此Throwable對(duì)象的堆棧跟蹤,添加到堆棧跟蹤中的任何以前的信息。

例子

下面是使用上面給出的一些方法的代碼示例 -

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println(ex.toString());
         println(ex.getMessage());
         println(ex.getStackTrace());  
      } catch(Exception ex) {
         println("Catching the exception");
      }finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
}

當(dāng)我們運(yùn)行上面的程序,我們將得到以下結(jié)果 -

java.lang.ArrayIndexOutOfBoundsException: 5 
5 
[org.codehaus.groovy.runtime.dgmimpl.arrays.IntegerArrayPutAtMetaMethod$MyPojoMetaMet 
hodSite.call(IntegerArrayPutAtMetaMethod.java:75), 
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) ,
Example.main(Sample:8), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93),
groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325),
groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1443),
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:893),
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:287),
groovy.lang.GroovyShell.run(GroovyShell.java:524),
groovy.lang.GroovyShell.run(GroovyShell.java:513),
groovy.ui.GroovyMain.processOnce(GroovyMain.java:652),
groovy.ui.GroovyMain.run(GroovyMain.java:384),
groovy.ui.GroovyMain.process(GroovyMain.java:370),
groovy.ui.GroovyMain.processArgs(GroovyMain.java:129),
groovy.ui.GroovyMain.main(GroovyMain.java:109),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:109),
org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:131),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)]
 
The final block 
Let's move on after the exception 
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)