Java例外処理
例外とはプログラム内の一部のエラーですが、すべてのエラーが例外であるわけではなく、エラーは回避できる場合もあります。
たとえば、コードにセミコロンがない場合、その実行結果はエラー java.lang.Error になります。System.out.println(11/0) を使用している場合は、0 を使用しているためです。除数を除いて、java.lang.ArithmeticException 例外がスローされます。
異常には多くの理由があり、通常は次のカテゴリが含まれます:
ユーザーが不正なデータを入力しました。
開こうとしたファイルが存在しません。
ネットワーク通信中に接続が中断されたか、JVM メモリがオーバーフローしました。
これらの例外の中には、ユーザー エラーによって発生するもの、プログラム エラーによって発生するもの、物理的なエラーによって発生するものもあります。 -
Java 例外処理がどのように機能するかを理解するには、次の 3 種類の例外をマスターする必要があります:
チェック例外: 最も代表的なチェック例外は、ユーザーのエラーや問題によって引き起こされる例外です。プログラマーは予測できません。たとえば、存在しないファイルを開こうとすると、コンパイル時にこれらの例外を単純に無視することはできません。
実行時例外: 実行時例外は、プログラマが回避できる例外です。チェック例外とは対照的に、実行時例外はコンパイル時に無視できます。
エラー: エラーは例外ではなく、プログラマの制御の及ばない問題です。コードではエラーが無視されることがよくあります。たとえば、スタックがオーバーフローすると、コンパイル時に確認できないエラーが発生します。
例外クラスの階層すべての例外クラスは、java.lang.Exception クラスから継承されたサブクラスです。 ExceptionクラスはThrowableクラスのサブクラスです。 Exception クラスに加えて、Throwable にはサブクラス Error もあります。 Java プログラムは通常、エラーをキャッチしません。エラーは通常、重大な障害が発生した場合に発生し、Java プログラムの処理の範囲外になります。 Error は、実行環境で発生するエラーを示すために使用されます。 たとえば、JVM メモリ オーバーフロー。通常、プログラムはエラーから回復できません。 例外クラスには、IOException クラスと RuntimeException クラスの 2 つの主要なサブクラスがあります。 Java 組み込みクラス (次に説明します) では、最も一般的に使用されるチェック例外と非チェック例外があります。
Java 組み込み例外クラス Java 言語は、java.lang 標準パッケージでいくつかの例外クラスを定義します。 標準ランタイム例外クラスのサブクラスは、最も一般的な例外クラスです。 java.lang パッケージはデフォルトですべての Java プログラムにロードされるため、ランタイム例外クラスから継承されたほとんどの例外を直接使用できます。
Java では、各クラス ライブラリに基づいて他の例外も定義されています。次の表に、Java の未チェック例外を示します。
例外 | 説明 |
---|---|
算術例外 | この例外は、異常な動作条件が発生した場合にスローされます。たとえば、整数が「ゼロで除算」されると、このクラスのインスタンスがスローされます。 |
ArrayIndexOutOfBoundsException | 不正なインデックスを持つ配列にアクセスすると例外がスローされます。インデックスが負の場合、または配列サイズ以上の場合、そのインデックスは不正なインデックスです。 |
ArrayStoreException | 間違った型のオブジェクトをオブジェクト配列に格納しようとすると例外がスローされました。 |
ClassCastException | この例外は、インスタンスではないサブクラスにオブジェクトをキャストしようとするとスローされます。 |
IllegalArgumentException | スローされた例外は、不正または不正なパラメーターがメソッドに渡されたことを示します。 |
IllegalMonitorStateException | スローされた例外は、スレッドがオブジェクトのモニターで待機しようとしたか、スレッド自体がモニターを指定せずにオブジェクトのモニターで待機している別のスレッドに通知しようとしたことを示します。 |
IllegalStateException | メソッドが不正または不適切なタイミングで呼び出されたときに生成されるシグナル。言い換えれば、Java 環境または Java アプリケーションは、要求された操作に対して適切な状態ではありません。 |
IllegalThreadStateException | スレッドが、要求された操作に必要な適切な状態にない場合にスローされる例外。 |
IndexOutOfBoundsException | ソート インデックス (配列、文字列、ベクトルのソートなど) が範囲外であることを示すときにスローされます。 |
NegativeArraySizeException | この例外は、アプリケーションが負のサイズの配列を作成しようとするとスローされます。 |
NullPointerException |
この例外は、アプリケーションがオブジェクトが必要な null を使用しようとしたときにスローされます |
NumberFormatException | この例外は、アプリケーションが文字列を数値型に変換しようとしたが、文字列を適切な形式に変換できない場合にスローされます。 |
SecurityException | セキュリティ違反を示すためにセキュリティ管理者によってスローされる例外。 |
StringIndexOutOfBoundsException |
この例外は String メソッドによってスローされ、インデックスが負であるか、文字列のサイズを超えていることを示します。 |
UnsupportedOperationException | この例外は、要求された操作がサポートされていない場合にスローされます。 |
次の表は、java.lang パッケージで Java によって定義されているチェック例外クラスをリストしています。
例外 | 説明 |
---|---|
ClassNotFoundException | アプリケーションがクラスをロードしようとすると、対応するクラスが見つからず、この例外がスローされます。 |
CloneNotSupportedException |
この例外は、Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable インターフェースが呼び出されたときにスローされます。 |
IllegalAccessException | この例外は、クラスへのアクセスが拒否された場合にスローされます。 |
インスタンス化例外 |
この例外は、Class 类中的 newInstance メソッドを使用してクラスのインスタンスを作成しようとしたときに、指定されたクラス オブジェクトがインターフェイスまたは抽象クラスであるためにインスタンス化できない場合にスローされます。 |
中断例外 | この例外は、スレッドが別のスレッドによって中断されたときにスローされます。 |
NoSuchFieldException | 要求された変数は存在しません |
NoSuchMethodException | 要求されたメソッドは存在しません |
例外メソッド
次のリストは、Throwable クラスのメインメソッドです:
シリアル番号 | メソッドと説明 |
---|---|
1 | public String getMessage() 発生した例外に関する詳細情報を返します。このメッセージは、Throwable クラスのコンストラクターで初期化されます。 |
2 | public Throwable getCause() 例外の原因を表す Throwable オブジェクトを返します。 |
3 | パブリック文字列 toString() getMessage() の結果を使用して、クラスの連結名を返します。 |
4 | public void printStackTrace() toString() の結果とスタック レベルをエラー出力ストリームである System.err に出力します。 |
5 | public StackTraceElement [] getStackTrace() スタックレベルを含む配列を返します。インデックス 0 の要素はスタックの最上位を表し、最後の要素はメソッド呼び出しスタックの最下位を表します。 |
6 | パブリックスロー可能fillInStackTrace() Throwable オブジェクトのスタック レベルに現在の呼び出しスタック レベルを設定し、スタック レベル内の以前の情報に追加します。 |
例外をキャッチする
例外をキャッチするには、try および catch キーワードを使用します。 Try/catch コード ブロックは、例外が発生する可能性のある場所に配置されます。
try/catch コード ブロック内のコードはガード コードと呼ばれます。try/catch を使用するための構文は次のとおりです。
try { // 程序代码 }catch(ExceptionName e1) { //Catch 块 }
Catch ステートメントには、キャッチする例外の種類の宣言が含まれます。保護されたコード ブロックで例外が発生すると、try に続く catch ブロックがチェックされます。
発生した例外がcatchブロックに含まれている場合、例外はcatchブロックに渡されます。これはメソッドにパラメータを渡すのと同じです。
例
次の例では、2 つの要素を持つ配列を宣言します。コードが配列の 3 番目の要素にアクセスしようとすると、例外がスローされます。
// 文件名 : 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{ // 程序代码 }catch(异常类型1 异常的变量名1){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }
上記のコード スニペットには 3 つの catch ブロックが含まれています。
try ステートメントの後には、任意の数の 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; }
throws/throw キーワード:
メソッドがチェック例外をキャッチしない場合、メソッドは throws キーワードを使用して宣言する必要があります。 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 }
finally キーワード
finally キーワードは、try コード ブロックの後に実行されるコード ブロックを作成するために使用されます。
例外が発生するかどうかに関係なく、finally コード ブロック内のコードは常に実行されます。
finally コード ブロックでは、クリーンアップ ステートメントやその他のクリーンアップ ステートメントを実行できます。
最後に、catch コード ブロックの最後にコード ブロックが表示されます。構文は次のとおりです。
try{ // 程序代码 }catch(异常类型1 异常的变量名1){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }finally{ // 程序代码 }
例
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 ブロックの間にコードを追加することはできません。
カスタム例外を宣言する
Java では例外をカスタマイズできます。独自の例外クラスを作成する場合は、留意すべき点がいくつかあります。
すべての例外は Throwable のサブクラスである必要があります。
チェック例外クラスを作成する場合は、Exception クラスを継承する必要があります。
ランタイム例外クラスを作成する場合は、RuntimeException クラスを継承する必要があります。
次のように独自の例外クラスを定義できます。
class MyException extends Exception{ }
Exception クラスのみを継承して作成された例外クラスは、チェック例外クラスです。
次の InsufficientFundsException クラスは、Exception を継承するユーザー定義の例外クラスです。
例外クラスは他のクラスと同様に、変数とメソッドを含みます。
例
// 文件名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 クラスにdraw() メソッドを組み込み、InsufficientFundsException 例外をスローします。
// 文件名称 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() メソッドとdrawr() メソッドを呼び出す方法を示しています。
//文件名称 BankDemo.java public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing 0..."); c.deposit(500.00); try { System.out.println("\nWithdrawing 0..."); c.withdraw(100.00); System.out.println("\nWithdrawing 0..."); c.withdraw(600.00); }catch(InsufficientFundsException e) { System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } }
上記の 3 つのファイルをコンパイルし、プログラム BankDemo を実行すると、結果は次のようになります:
Depositing 0... Withdrawing 0... Withdrawing 0... Sorry, but you are short 0.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)
一般例外
Java では 2 種類の例外とエラーが定義されています。
JVM (Java仮想マシン)Exception: JVM によってスローされた例外またはエラー。例: NullPointerException クラス、ArrayIndexOutOfBoundsException クラス、ClassCastException クラス。
プログラムレベルの例外: プログラムまたはAPIプログラムによってスローされた例外。たとえば、IllegalArgumentException クラス、IllegalStateException クラスです。