Java-例外

例外(または例外イベント)は、プログラムの実行中に発生する問題です。いつException プログラムの通常のフローが中断され、プログラム/アプリケーションが異常終了することが発生します。これはお勧めできません。したがって、これらの例外を処理する必要があります。

例外はさまざまな理由で発生する可能性があります。以下は、例外が発生するいくつかのシナリオです。

  • ユーザーが無効なデータを入力しました。

  • 開く必要のあるファイルが見つかりません。

  • 通信の途中でネットワーク接続が失われたか、JVMのメモリが不足しています。

これらの例外のいくつかは、ユーザーエラー、プログラマーエラー、および何らかの方法で障害が発生した物理リソースが原因で発生します。

これらに基づいて、例外の3つのカテゴリがあります。Javaで例外処理がどのように機能するかを知るには、それらを理解する必要があります。

  • Checked exceptions−チェック例外は、コンパイル時にコンパイラによってチェック(通知)される例外であり、コンパイル時例外とも呼ばれます。これらの例外は単純に無視することはできません。プログラマーはこれらの例外を処理(処理)する必要があります。

たとえば、 FileReaderプログラム内のクラスでファイルからデータを読み取る場合、コンストラクターで指定されたファイルが存在しない場合、FileNotFoundExceptionが発生し、コンパイラーはプログラマーに例外の処理を要求します。

import java.io.File;
import java.io.FileReader;

public class FilenotFound_Demo {

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

上記のプログラムをコンパイルしようとすると、次の例外が発生します。

出力

C:\>javac FilenotFound_Demo.java
FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
      FileReader fr = new FileReader(file);
                      ^
1 error

Note −メソッド以来 read() そして close() FileReaderクラスがIOExceptionをスローすると、コンパイラがFileNotFoundExceptionとともにIOExceptionを処理するように通知することがわかります。

  • Unchecked exceptions−チェックされていない例外は、実行時に発生する例外です。これらは、Runtime Exceptions。これには、論理エラーやAPIの不適切な使用などのプログラミングのバグが含まれます。実行時の例外は、コンパイル時に無視されます。

たとえば、プログラムでサイズ5の配列を宣言し、配列の6番目の要素を呼び出そうとすると、ArrayIndexOutOfBoundsExceptionexceptionが発生します。

public class Unchecked_Demo {
   
   public static void main(String args[]) {
      int num[] = {1, 2, 3, 4};
      System.out.println(num[5]);
   }
}

上記のプログラムをコンパイルして実行すると、次の例外が発生します。

出力

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
	at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
  • Errors−これらはまったく例外ではありませんが、ユーザーまたはプログラマーの制御を超えて発生する問題です。エラーについてはほとんど何もできないため、エラーは通常、コードでは無視されます。たとえば、スタックオーバーフローが発生すると、エラーが発生します。また、コンパイル時には無視されます。

例外階層

すべての例外クラスは、java.lang.Exceptionクラスのサブタイプです。例外クラスは、Throwableクラスのサブクラスです。例外クラスの他に、Throwableクラスから派生したErrorと呼ばれる別のサブクラスがあります。

エラーは、重大な障害が発生した場合に発生する異常な状態であり、Javaプログラムでは処理されません。エラーは、ランタイム環境によって生成されたエラーを示すために生成されます。例:JVMのメモリが不足しています。通常、プログラムはエラーから回復できません。

Exceptionクラスには、IOExceptionクラスとRuntimeExceptionクラスの2つの主要なサブクラスがあります。

以下は、最も一般的なチェック済みおよびチェックなしのJavaの組み込み例外のリストです。

例外メソッド

以下は、Throwableクラスで使用可能な重要なメソッドのリストです。

シニア番号 方法と説明
1

public String getMessage()

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

2

public Throwable getCause()

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

3

public String toString()

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

4

public void printStackTrace()

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

5

public StackTraceElement [] getStackTrace()

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

6

public Throwable fillInStackTrace()

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

例外をキャッチする

メソッドは、との組み合わせを使用して例外をキャッチします try そして catchキーワード。例外を生成する可能性のあるコードの周囲にtry / catchブロックが配置されます。try / catchブロック内のコードは保護されたコードと呼ばれ、try / catchを使用するための構文は次のようになります。

構文

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

例外が発生しやすいコードは、tryブロックに配置されます。例外が発生すると、発生したその例外は、それに関連付けられたcatchブロックによって処理されます。すべてのtryブロックの直後に、catchブロックまたはfinallyブロックが続く必要があります。

catchステートメントには、キャッチしようとしている例外のタイプを宣言することが含まれます。保護されたコードで例外が発生した場合、試行に続く1つまたは複数のcatchブロックがチェックされます。発生した例外のタイプがcatchブロックにリストされている場合、引数がメソッドパラメーターに渡されるのと同じように、例外がcatchブロックに渡されます。

以下は、2つの要素で宣言された配列です。次に、コードは、例外をスローする配列の3番目の要素にアクセスしようとします。

// File Name : ExcepTest.java
import java.io.*;

public class ExcepTest {

   public static void main(String args[]) {
      try {
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      } catch (ArrayIndexOutOfBoundsException e) {
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

これにより、次の結果が生成されます-

出力

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

複数のキャッチブロック

tryブロックの後に複数のcatchブロックを続けることができます。複数のcatchブロックの構文は次のようになります-

構文

try {
   // Protected code
} catch (ExceptionType1 e1) {
   // Catch block
} catch (ExceptionType2 e2) {
   // Catch block
} catch (ExceptionType3 e3) {
   // Catch block
}

前のステートメントは3つのcatchブロックを示していますが、1回の試行で任意の数のcatchブロックを使用できます。保護されたコードで例外が発生した場合、例外はリストの最初のcatchブロックにスローされます。スローされた例外のデータ型がExceptionType1と一致する場合、そこでキャッチされます。そうでない場合、例外は2番目のcatchステートメントに渡されます。これは、例外がキャッチされるか、すべてのキャッチを通過するまで続きます。その場合、現在のメソッドは実行を停止し、例外は呼び出しスタック上の前のメソッドにスローされます。

これは、複数のtry / catchステートメントの使用方法を示すコードセグメントです。

try {
   file = new FileInputStream(fileName);
   x = (byte) file.read();
} catch (IOException i) {
   i.printStackTrace();
   return -1;
} catch (FileNotFoundException f) // Not valid! {
   f.printStackTrace();
   return -1;
}

複数のタイプの例外をキャッチする

Java 7以降、単一のcatchブロックを使用して複数の例外を処理できるため、この機能によりコードが簡素化されます。これがあなたがそれをする方法です-

catch (IOException|FileNotFoundException ex) {
   logger.log(ex);
   throw ex;

スロー/スローキーワード

メソッドがチェックされた例外を処理しない場合、メソッドはを使用してそれを宣言する必要があります throwsキーワード。throwsキーワードは、メソッドのシグネチャの最後に表示されます。

を使用して、新しくインスタンス化された例外またはキャッチしたばかりの例外のいずれかの例外をスローできます。 throw キーワード。

throwsキーワードとthrowキーワードの違いを理解してください。throwsはチェックされた例外の処理を延期するために使用され、throwは例外を明示的に呼び出すために使用されます。

次のメソッドは、RemoteExceptionをスローすることを宣言します-

import java.io.*;
public class className {

   public void deposit(double amount) throws RemoteException {
      // Method implementation
      throw new RemoteException();
   }
   // Remainder of class definition
}

メソッドは、複数の例外をスローすることを宣言できます。その場合、例外はコンマで区切られたリストで宣言されます。たとえば、次のメソッドは、RemoteExceptionとInsufficientFundsExceptionをスローすることを宣言しています-

import java.io.*;
public class className {

   public void withdraw(double amount) throws RemoteException, 
      InsufficientFundsException {
      // Method implementation
   }
   // Remainder of class definition
}

最後にブロック

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

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

finishブロックは、catchブロックの最後に表示され、次の構文になります。

構文

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

public class ExcepTest {

   public static void main(String args[]) {
      int a[] = new int[2];
      try {
         System.out.println("Access element three :" + a[3]);
      } catch (ArrayIndexOutOfBoundsException e) {
         System.out.println("Exception thrown  :" + e);
      }finally {
         a[0] = 6;
         System.out.println("First element value: " + a[0]);
         System.out.println("The finally statement is executed");
      }
   }
}

これにより、次の結果が生成されます-

出力

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

次の点に注意してください-

  • catch句は、tryステートメントなしでは存在できません。

  • try / catchブロックが存在する場合は常に、finally句を含める必要はありません。

  • tryブロックは、catch句またはfinally句なしでは存在できません。

  • try、catch、finallyブロックの間にコードを含めることはできません。

リソースを試す

一般に、ストリームや接続などのリソースを使用する場合は、finallyブロックを使用して明示的に閉じる必要があります。次のプログラムでは、を使用してファイルからデータを読み取っています。FileReader そしてfinallyブロックを使用して閉じています。

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]) {
      FileReader fr = null;		
      try {
         File file = new File("file.txt");
         fr = new FileReader(file); char [] a = new char[50];
         fr.read(a);   // reads the content to the array
         for(char c : a)
         System.out.print(c);   // prints the characters one by one
      } catch (IOException e) {
         e.printStackTrace();
      }finally {
         try {
            fr.close();
         } catch (IOException ex) {		
            ex.printStackTrace();
         }
      }
   }
}

try-with-resources、とも呼ばれます automatic resource managementは、Java 7で導入された新しい例外処理メカニズムであり、trycatchブロック内で使用されているリソースを自動的に閉じます。

このステートメントを使用するには、括弧内に必要なリソースを宣言するだけで、作成されたリソースはブロックの最後で自動的に閉じられます。以下は、try-with-resourcesステートメントの構文です。

構文

try(FileReader fr = new FileReader("file path")) {
   // use the resource
   } catch () {
      // body of catch 
   }
}

以下は、try-with-resourcesステートメントを使用してファイル内のデータを読み取るプログラムです。

import java.io.FileReader;
import java.io.IOException;

public class Try_withDemo {

   public static void main(String args[]) {
      try(FileReader fr = new FileReader("E://file.txt")) {
         char [] a = new char[50];
         fr.read(a);   // reads the contentto the array
         for(char c : a)
         System.out.print(c);   // prints the characters one by one
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

try-with-resourcesステートメントを使用するときは、次の点に注意してください。

  • try-with-resourcesステートメントでクラスを使用するには、実装する必要があります AutoCloseable インターフェースと close() そのメソッドは実行時に自動的に呼び出されます。

  • try-with-resourcesステートメントで複数のクラスを宣言できます。

  • try-with-resourcesステートメントのtryブロックで複数のクラスを宣言している間、これらのクラスは逆の順序で閉じられます。

  • 括弧内のリソースの宣言を除いて、すべてがtryブロックの通常のtry / catchブロックと同じです。

  • tryで宣言されたリソースは、try-blockの開始直前にインスタンス化されます。

  • tryブロックで宣言されたリソースは、暗黙的にfinalとして宣言されます。

ユーザー定義の例外

Javaで独自の例外を作成できます。独自の例外クラスを作成するときは、次の点に注意してください。

  • すべての例外はThrowableの子である必要があります。

  • HandleまたはDeclareRuleによって自動的に適用されるチェック済み例外を作成する場合は、Exceptionクラスを拡張する必要があります。

  • ランタイム例外を記述したい場合は、RuntimeExceptionクラスを拡張する必要があります。

独自のExceptionクラスを次のように定義できます-

class MyException extends Exception {
}

事前定義されたものを拡張する必要があります Exception独自の例外を作成するクラス。これらはチェックされた例外と見なされます。以下InsufficientFundsExceptionclassは、Exceptionクラスを拡張するユーザー定義の例外であり、チェックされた例外になります。例外クラスは他のクラスと同様で、便利なフィールドとメソッドが含まれています。

// File Name InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception {
   private double amount;
   
   public InsufficientFundsException(double amount) {
      this.amount = amount;
   }
   
   public double getAmount() {
      return amount;
   }
}

ユーザー定義の例外の使用を示すために、次のCheckingAccountクラスには、InsufficientFundsExceptionをスローするwithdraw()メソッドが含まれています。

// File Name CheckingAccount.java
import java.io.*;

public class CheckingAccount {
   private double balance;
   private int number;
   
   public CheckingAccount(int number) {
      this.number = number;
   }
   
   public void deposit(double amount) {
      balance += amount;
   }
   
   public void withdraw(double amount) throws InsufficientFundsException {
      if(amount <= balance) {
         balance -= amount;
      }else {
         double needs = amount - balance;
         throw new InsufficientFundsException(needs);
      }
   }
   
   public double getBalance() {
      return balance;
   }
   
   public int getNumber() {
      return number;
   }
}

次のBankDemoプログラムは、CheckingAccountのdeposit()メソッドとwithdraw()メソッドの呼び出しを示しています。

// File Name BankDemo.java
public class BankDemo {

   public static void main(String [] args) {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);
      
      try {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);
      } catch (InsufficientFundsException e) {
         System.out.println("Sorry, but you are short $" + e.getAmount());
         e.printStackTrace();
      }
   }
}

上記の3つのファイルをすべてコンパイルし、BankDemoを実行します。これにより、次の結果が生成されます-

出力

Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
         at CheckingAccount.withdraw(CheckingAccount.java:25)
         at BankDemo.main(BankDemo.java:13)

一般的な例外

Javaでは、例外とエラーの2つのカテゴリを定義できます。

  • JVM Exceptions−これらは、JVMによって排他的または論理的にスローされる例外/エラーです。例:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。

  • Programmatic Exceptions−これらの例外は、アプリケーションまたはAPIプログラマーによって明示的にスローされます。例:IllegalArgumentException、IllegalStateException。