Java異常のキャプチャと処理の詳細(二)

14510 ワード

前回のJava異常のキャプチャと処理の詳細(一)異常の発生,処理および処理の流れについて述べ,次に他の内容について述べる.
一、throwsキーワード
thrwosキーワードは主にメソッド定義で用いられ,このメソッドでは異常な処理を行わずに呼び出された処理に渡すことを示す.
例:
class MyMath {
    public int div(int x, int y) throws Exception {
        return x / y;
    }
}

現在のdiv()メソッドでは,すべての例外が呼び出し先に渡されて処理されることを示す例外が投げ出されている.
class MyMath {
    public int div(int x, int y) throws Exception {
        return x / y;
    }
}

public class Test {
    public static void main(String args[]) {
        try {
            System.out.println(new MyMath().div(10, 0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果:
java.lang.ArithmeticException: / by zero
    at MyMath.div(Test.java:3)
    at Test.main(Test.java:10)

注意:throws宣言メソッドを呼び出す場合は、例外処理操作を使用して例外の処理を行う必要があります.これは強制的な処理です.
プライマリ・メソッド自体もメソッドに属し、プライマリ・メソッドではthrowsを使用して異常な放出を継続することもできます.
class MyMath {
    public int div(int x, int y) throws Exception {
        return x / y;
    }
}

public class Test {
    public static void main(String args[]) throws Exception {
        System.out.println(new MyMath().div(10, 0));
    }
}

実行結果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at MyMath.div(Test.java:3)
    at Test.main(Test.java:9)

このときメインメソッドは異常を上に投げ続け,JVMに渡して異常の処理を行う,すなわちデフォルト方式で異常情報を出力し,プログラム実行を終了する.
注意:実際の開発では、主な方法はthrowsを追加しないでください.プログラムに異常があれば、私たちも正常に終了することを望んでいます.
二、throwキーワード
以前はすべての例外クラスオブジェクトがJVMによって自動的にインスタンス化されていましたが、ユーザーは自分で例外クラスインスタンス化オブジェクトを手動で投げ出すことができ、throwで完了しました.
public class Test {
    public static void main(String args[]) {
        try {
            throw new Exception("      ");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果:
java.lang.Exception:       
    at Test.main(Test.java:4)

小結:throwとthrowsの違いは?
(1)throw:メソッド内で使用し、人為的に異常クラスオブジェクトを投げ出すことを表す(このオブジェクトは自分でインスタンス化してもよいし、既存であってもよい).(2)throws:メソッドの宣言に用いられ,このメソッドでは異常な処理を行わずに呼び出された処理に渡すことを示す.
三、異常処理標準フォーマット
私たちはfinallyとthrowが役に立たないと感じています.次に、div()メソッドを定義することが要求される.このメソッドには、(1)除算操作を行う前に、1行のヒント情報を出力する.(2)除算操作の実行が完了した後、1行のヒント情報を出力する.(3)中間に異常が発生した場合は,呼び出し先に渡して処理すべきである.
class MyMath {
    //             ,  throws
    public int div(int x, int y) throws Exception {
        System.out.println("=====      ====="); 
        int result = 0;
        try {
            result = x / y; //     
        } catch (Exception e) {
            throw e; //    
        } finally {
            System.out.println("=====      ====="); 
        }
        return result;
    }
}

public class Test {
    public static void main(String args[]) {
        try {
            System.out.println(new MyMath().div(10, 0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果:
=====      =====
=====      =====
java.lang.ArithmeticException: / by zero
    at MyMath.div(Test.java:7)
    at Test.main(Test.java:20)

上記のコードは、いくつかの簡略化も可能です.
class MyMath {
    //             ,  throws
    public int div(int x, int y) throws Exception {
        System.out.println("=====      ====="); 
        int result = 0;
        try {
            result = x / y; //     
        } finally {
            System.out.println("=====      =====");
        }
        return result;
    }
}

public class Test {
    public static void main(String args[]) {
        try {
            System.out.println(new MyMath().div(10, 0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果:
=====      =====
=====      =====
java.lang.ArithmeticException: / by zero
    at MyMath.div(Test.java:7)
    at Test.main(Test.java:18)

try...finallyを直接使用し、catchを持たないと処理する機会もないので、try...finallyはお勧めしません.標準フォーマットはtry...catch、finally、throws、throwとともに使用されます.
四、RuntimeException類
まずコードを見てみましょう
public class Test {
    public static void main(String args[]) {
        String str = "123";
        int num = Integer.parseInt(str);
        System.out.println(num * num);
    }
}

実行結果:
15129

このプログラムは、文字列を基本データ型に変更して乗算を実行しますが、parseInt()メソッド定義を見てみましょう.
public static int parseInt(String s) throws NumberFormatException

この方法にNumberFormatExceptionの異常が投げ出されていることに気づき、前述したようにthrowsが存在する場合はtry...catchを用いて処理しなければならないが、現在は強制的に処理を要求していないのはなぜだろうか.NumberFormatExceptionの継承構造を見てみましょう.
java.lang.Object
   |- java.lang.Throwable
      |- java.lang.Exception
          |- java.lang.RuntimeException
              |- java.lang.IllegalArgumentException
                  |- java.lang.NumberFormatException

NumberFormatExceptionはRuntimeExceptionのサブクラスであることが判明したが,JavaではRuntimeExceptionの異常タイプについてはコンパイル時に強制的にユーザに処理を要求することはなく,ユーザは必要に応じて選択的に処理することができ,開発中に処理がなければ異常が発生した後にJVMにデフォルトで処理を任せることを明確に規定している.すなわち,RuntimeExceptionのサブ例外クラスは,ユーザが必要に応じて選択的に処理できる.
まとめ:RuntimeExceptionとExceptionの違いは?よくあるRuntimeExceptionをいくつか挙げてください.
(1)RuntimeExceptionはExceptionのサブクラスである.(2)Exceptionは処理すべき例外を定義し,RuntimeExceptionが定義した例外は選択的に処理できる.
一般的なRuntimeException:NumberFormatException、ClassCastException、Null PointerException、ArithmeticException、ArrayIndexOutOfBoundsException.
五、assertキーワード(断言)
Javaでは、プログラムがローに実行された後、その結果は予想された結果に違いないと断言し、JDK 1.4以降にassertキーワードが追加された.
2つの文法形式:(1)形式1:
assert condition;

ここでconditionは真(true)でなければならない式です.式の結果がtrueの場合、断言は真であり、アクションはありません.式がfalseの場合、断言に失敗すると、AssertionErrorオブジェクトが放出されます.このAssertionErrorはErrorオブジェクトに継承されます.
(2)形式2:
asser condition:expr;

ここでconditionは上と同じで、このコロンの後に続く式で、通常は断言に失敗した後のヒント情報に用いられ、はっきり言って、AssertionError構造関数に伝わる値であり、断言に失敗した場合、その値は対応する文字列に変換され、表示されます.
アサーションの使用:
public class Test {
    public static void main(String args[]) {
        int x = 10;
        //          
        assert x == 30 : "x     30";
        System.out.println(x);
    }
}

デフォルトでは、Javaのアサーションは、通常実行されるコードには表示されません.アサーションを有効にするには、-eaオプションを追加する必要があります.
java -ea Test

実行結果:
Exception in thread "main" java.lang.AssertionError: x     30
        at Test.main(Test.java:5)

六、カスタム例外
Javaではそれ自体に多くの例外タイプが提供されているが,開発ではこれらの例外タイプが開発のニーズを満たすことはできない.そのため、いくつかのシステムアーキテクチャでは、いくつかの新しい例外タイプが提供され、いくつかの特殊なエラーを表すことがよくあります.この操作はカスタム例外クラスと呼ばれ、このカスタム例外クラスを実現するには、クラスにExceptionまたはRuntimeExceptionを継承させることができます.
class MyException extends Exception { //       
    public MyException(String msg) {
        super(msg);
    }
}

public class Test {
    public static void main(String args[]) throws Exception {
        throw new MyException("      ");
    }
}

実行結果:
Exception in thread "main" MyException:       
    at Test.main(Test.java:9)