Groovy-例外処理

アプリケーションの通常のフローを維持できるように、ランタイムエラーを処理するには、プログラミング言語で例外処理が必要です。

例外は通常、アプリケーションの通常のフローを中断します。これが、アプリケーションで例外処理を使用する必要がある理由です。

例外は大きく次のカテゴリに分類されます-

  • Checked Exception − RuntimeExceptionとErrorを除いてThrowableクラスを拡張するクラスは、チェック例外(IOException、SQLExceptionなど)と呼ばれます。チェック例外はコンパイル時にチェックされます。

古典的なケースの1つは、FileNotFoundExceptionです。Eドライブ内のファイルから読み取るアプリケーションに次のコードがあるとします。

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

ファイル(file.txt)がEドライブにない場合、次の例外が発生します。

キャッチ:java.io.FileNotFoundException:E:\ file.txt(システムは指定されたファイルを見つけることができません)。

java.io.FileNotFoundException:E:\ file.txt(システムは指定されたファイルを見つけることができません)。

  • Unchecked Exception − RuntimeExceptionを拡張するクラスは、未チェックの例外と呼ばれます。たとえば、ArithmeticException、NullPointerException、ArrayIndexOutOfBoundsExceptionなどです。未チェックの例外は、コンパイル時にチェックされず、実行時にチェックされます。

古典的なケースの1つは、配列の長さよりも大きい配列のインデックスにアクセスしようとしたときに発生するArrayIndexOutOfBoundsExceptionです。以下は、この種の間違いの典型的な例です。

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

上記のコードを実行すると、次の例外が発生します。

キャッチ:java.lang.ArrayIndexOutOfBoundsException:5

java.lang.ArrayIndexOutOfBoundsException:5

  • Error −エラーは回復不能です(例:OutOfMemoryError、VirtualMachineError、AssertionErrorなど)。

これらは、プログラムが回復できないエラーであり、プログラムをクラッシュさせる原因になります。

次の図は、Groovyの例外の階層がどのように編成されているかを示しています。これはすべて、Javaで定義された階層に基づいています。

例外をキャッチする

メソッドは、との組み合わせを使用して例外をキャッチします try そして catchキーワード。例外を生成する可能性のあるコードの周囲にtry / catchブロックが配置されます。

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

例外を発生させる可能性のあるすべてのコードは、保護されたコードブロックに配置されます。

catchブロックでは、アプリケーションが例外から回復できるように、例外を処理するカスタムコードを記述できます。

配列のサイズよりも大きいインデックス値を持つ配列にアクセスするために上で見た同様のコードの例を見てみましょう。しかし今回は、コードを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");
   }
}

上記のプログラムを実行すると、次の結果が得られます-

Catching the exception 
Let's move on after the exception

上記のコードから、tryブロックで障害のあるコードをラップします。catchブロックでは、例外をキャッチして、例外が発生したというメッセージを出力しています。

複数のキャッチブロック

複数のタイプの例外を処理するために、複数のcatchブロックを持つことができます。発生した例外のタイプに応じて、catchブロックごとに、それに応じて処理するコードを記述します。

上記のコードを変更して、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");
   } 
}

上記のプログラムを実行すると、次の結果が得られます-

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

上記のコードから、ArrayIndexOutOfBoundsExceptionキャッチブロックが最初にキャッチされることがわかります。これは、例外の基準を意味するためです。

最後にブロック

ザ・ finallyブロックは、tryブロックまたはcatchブロックの後に続きます。例外の発生に関係なく、コードのfinallyブロックは常に実行されます。

finishブロックを使用すると、保護されたコードで何が起こっても、実行したいクリーンアップタイプのステートメントを実行できます。このブロックの構文を以下に示します。

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

上記のプログラムを実行すると、次の結果が得られます-

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

以下は、Groovyで使用可能なExceptionメソッドです。

public String getMessage()

発生した例外に関する詳細メッセージを返します。このメッセージは、Throwableコンストラクターで初期化されます。

public Throwable getCause()

Throwableオブジェクトで表される例外の原因を返します。

public String toString()

getMessage()の結果と連結されたクラスの名前を返します

public void printStackTrace()

toString()の結果をスタックトレースとともにエラー出力ストリームであるSystem.errに出力します。

public StackTraceElement [] getStackTrace()

スタックトレース上の各要素を含む配列を返します。インデックス0の要素は呼び出しスタックの最上位を表し、配列の最後の要素は呼び出しスタックの最下部のメソッドを表します。

public Throwable fillInStackTrace()

このThrowableオブジェクトのスタックトレースを現在のスタックトレースで埋め、スタックトレースの以前の情報に追加します。

以下は、上記の方法のいくつかを使用したコード例です。

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

上記のプログラムを実行すると、次の結果が得られます-

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