1. 例外

>

ついに、プログラマはエラー処理を標準化して自動化することを考えました。これは例外が発明されたときに起こりました。現在、例外メカニズムは例外状況の 80% を処理します。

学者が例外を思いついた場合、それが博士論文の主題となる可能性があります。プログラマーがそれを思いついたとしたら、同僚から「大丈夫みたいだね、兄さん」と優しく背中を押してもらったかもしれません。

Java プログラムで除算などのエラーが発生すると、0次のような素晴らしいことが起こります。

第一歩

発生したエラーに関する情報を含む特別な例外オブジェクトが作成されます。

Java ではすべてがオブジェクトであり、例外も例外ではありません 🙂 例外オブジェクトには独自のクラスがあり、通常のクラスと唯一異なるのは、クラスを継承することですThrowable

ステップ2

例外オブジェクトは「スロー」されます。おそらくここでの表現はもっと良いかもしれません。「例外をスローする」ということは、火災警報器を作動させたり、「DEFCON 1」アラートを鳴らしたりすることに似ています。

Java マシンに例外がスローされると、プログラムの通常の動作が停止し、「緊急プロトコル」が開始されます。

ステップ 3

例外がスローされたメソッドは直ちに終了します。例外は呼び出しメソッドに渡され、メソッドもすぐに終了します。メソッドが終了するまで、チェーンを下っていきますmain。メソッドが終了するとmain、プログラムも終了します。

例:

コード コンソール出力
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Your attention, please! Preparing for the end of the world");
      endTheWorld();
      System.out.println("The world ended successfully");
   }

   public static void endTheWorld()
   {
      System.out.println("We're doing something important");
      doSomeWork(0);
      System.out.println("Everything is working well");
   }

   public static void doSomeWork(int n)
   {
      System.out.println("Nothing terrible will happen: " + n);
      System.out.println(2 / n);
      System.out.println("Nothing terrible happened: " + n);
   }
}
Your attention, please! Preparing for the end of the world
We're doing something important
Nothing terrible will happen: 0

20 行目: 0 による除算で例外が発生します。Javaマシンはすぐに例外(オブジェクト) を作成しArithmeticException、それをメソッドに「スロー」します。

メソッドdivide()はすぐに終了するため、次の文字列は表示されません: Nothing worst happens: 0. プログラムはメソッドに戻りendTheWorld()、状況が繰り返されます。システム内に未処理の例外があり、これはメソッドendTheWorld()も異常終了することを意味します。その後、mainメソッドが終了し、プログラムが停止します。

これらの例外の目的は何ですか? 独自のコードを作成して特定の種類の例外をキャッチしたり、例外的な状況を処理する独自のロジックを作成したりできます。


2. 例外のキャッチ:try-catch

Java には、このメソッドの異常終了を停止できる例外キャッチ メカニズムがあります。次のようになります。

try
{
   // Code where an exception might occur
}
catch(ExceptionType name)
{
   // Exception handling code
}

この構成体はtry-catchブロックと呼ばれます。

例外が発生する可能性のあるコードは中括弧で囲まれ、その前に という単語が付きますtry

中括弧の後にキーワードがありcatch括弧内に例外変数の宣言があります。この後には、指定されたタイプの例外が発生した場合に実行されるコードを囲む中括弧が続きます

「プライマリ コード」の実行中に例外がスローされない場合、catch ブロック内のコードは実行されません。例外が発生した場合は、例外が発生します (スローされた例外の型が括弧内の変数の型と同じである場合)。

例:

コード コンソール出力
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Hadron Collider launched");

      try
      {
         launchHadronCollider(1);
         launchHadronCollider(0);
      }
      catch(Exception e)
      {
         System.out.println("Error! Caught an exception");
         System.out.println("The planet was sucked into a black hole!");
      }

      System.out.println("The Hadron Collider stopped");
   }

   public static void launchHadronCollider(int n)
   {
      System.out.println("Everything is working well: " + n);
      System.out.println(2/n);
      System.out.println("There are no problems: " + n);
   }
}
Hadron Collider launched
Everything is working fine: 1
2
There are no problems: 1
Everything is working fine: 0
Error! Caught an exception
The planet has been sucked into a black hole!
The Hadron Collider is stopped


3. 複数のcatchブロック

複数のキャッチブロック

理論的には、コード ブロック内であらゆる種類の例外をスローできます。ある方法で処理したいものもあれば、別の方法で処理したいものもあれば、まったく処理しないことに決めたものもあります。

Java 開発者は、あなたを支援し、ブロックcatchの後に 1 つではなく多くのブロックを記述できるようにすることにしましたtry

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 name1)
{
   // Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
   // Code for handling ExceptionType2
}
   catch (ExceptionType3 name3)
{
   // Code for handling ExceptionType3
}

例:

コード コンソール出力
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch (ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method


catch4.ブロックの順序

ブロック内で発生した例外は、try単一のブロックでのみキャッチできますcatch。複数のブロックのコードが実行される例外処理状況は発生できませんcatch

ただし、ブロックの順序は重要です。

複数のブロックによって例外がキャッチされる状況が発生する可能性があります。その場合、例外は最初に来る (ブロックに最も近い) catchブロックによってキャッチされます。try

複数の catch ブロックが同じ例外をキャッチできる状況はどのようにして発生するのでしょうか?

すべての例外は単一の継承階層に属します。図を参照してください。

例外階層

オブジェクトArithmeticExceptionは、タイプが である変数、ArithmeticExceptionまたはその祖先クラスのいずれかに割り当てることができます: RuntimeExceptionおよびExceptionThrowable図を参照してください。

継承クラスと祖先クラスについてはレベル 21 で詳しく説明します。

このコードは問題なくコンパイルされます。

継承の利点:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

ArithmeticExceptionしたがって、上記の4 つのブロックのいずれかを使用してをキャッチできますcatch

例 1:

コード コンソール出力
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method

この例では、 はとブロックArithmeticExceptionの両方でキャッチできます。ブロックに最も近いブロック、つまり最初のブロックによってキャッチされます。catch (Exception e)catch (ArithmeticException e)trycatch

catch予期せぬ事態を避けるには、ほぼすべての例外をキャッチできるブロックをブロックのリストの最後近くに配置するのが最善ですcatch

このThrowable型は通常、Java で発生する可能性のあるすべての例外をキャッチできます。これを最初のブロックに置くとcatch、コンパイラは到達できないコード ブロックがあることを認識するため、コードはコンパイルされません。