ホームページ  >  記事  >  Java  >  Java例外処理メカニズムの深い理解

Java例外処理メカニズムの深い理解

伊谢尔伦
伊谢尔伦オリジナル
2016-11-26 11:12:091297ブラウズ

1. はじめに

try…catch…finallyはおそらく誰にとっても馴染みのある文であり、非常に使いやすく、論理的に理解しやすいと感じます。しかし、私が個人的に経験した「教訓」は、これは私が想像しているほど単純で従順なものではないことを教えてくれます。信じないで?次に、次のコードを見て、実行後の結果がどのようになるかを「推測」してください。答えを振り返ったり、実際の答えを確認するためにコードを実行したりしないでください。あなたの答えが正しければ、この記事を読んで時間を無駄にする必要はありません。

rreee

あなたの答えは何ですか?下記の答えでしょうか?

i=2
i=1
testEx2、catch例外
testEx2、finally; return value=false
testEx1、catch例外
testEx、finally; あなたの答えが本当にであるなら。上で述べたように、それならあなたは間違っています。 ^_^ では、この記事を注意深く読むか、上記のコードを使用して、さまざまな状況でコードを変更、実行、テストすることをお勧めします。多くのことが当初想像していたほど単純ではないことがわかります。正解が発表されます:

i=2

i=1

testEx2、catch例外

testEx1、finally; return value=false


; :

finally ステートメント ブロックは出現せず、return が出現する必要があります。上記の return ret は、関連ロジックを処理するために他のステートメントで使用するのが最適です。

2. JAVA例外

例外とは、ファイルが見つからない、ネットワーク接続の失敗、不正なパラメータなど、さまざまな予期しない状況を指します。例外は、プログラムの実行中に発生し、通常の命令フローを妨げるイベントです。 Java は、API の Throwable クラスの多数のサブクラスを通じてさまざまな例外を記述します。したがって、Java 例外は、コーディングの一部で発生するエラー条件を記述するオブジェクト、つまり Throwable サブクラスのインスタンスです。 Error は、条件が生成されたときに例外をスローします。

Java 例外クラス階層図:

Java では、すべての例外は共通の祖先 Throwable (throwable) を持ちます。 Throwable は、例外伝播メカニズムを使用して Java アプリケーションを通じて伝播できるコード内の問題の共通性を指定します。

Throwable: Exception (例外) と Error (エラー) の 2 つの重要なサブクラスがあり、どちらも Java 例外処理の重要なサブクラスであり、それぞれに多数のサブクラスが含まれています。

Java例外処理メカニズムの深い理解 エラー: プログラムが処理できないエラーであり、アプリケーションの実行に重大な問題があることを示しています。ほとんどのエラーは、コード作成者が実行したアクションとは何の関係もなく、コードの実行中の JVM (Java 仮想マシン) の問題を表します。たとえば、Java 仮想マシンの実行エラー (Virtual MachineError) では、操作の実行を継続するために必要なメモリ リソースが JVM になくなったときに、OutOfMemoryError が発生します。これらの例外が発生すると、Java 仮想マシン (JVM) は通常、スレッドを終了することを選択します。

これらのエラーは、Java 仮想マシン実行エラー (Virtual MachineError)、クラス定義エラー (NoClassDefFoundError) など、仮想マシン自体で障害が発生しているか、仮想マシンがアプリケーションを実行しようとしたときに発生したことを示します。これらのエラーはアプリケーション プログラムの制御および処理能力の範囲外にあるためチェックできません。また、そのほとんどはプログラムの実行中に発生することが許されない状態です。適切に設計されたアプリケーションの場合、たとえエラーが発生したとしても、それによって引き起こされた例外を処理しようとする必要はありません。 Java では、エラーは Error のサブクラスを通じて記述されます。

例外: プログラム自体が処理できる例外です。

Exceptionクラスには重要なサブクラスRuntimeExceptionがあります。 RuntimeException クラスとそのサブクラスは、「一般的な JVM 操作」によって引き起こされるエラーを表します。たとえば、NULL オブジェクト参照を使用しようとした場合、ゼロで除算した場合、または配列が範囲外の場合は、実行時例外 (NullPointerException、ArithmeticException) および ArrayIndexOutOfBoundException がそれぞれスローされます。

注: 例外とエラーの違い: 例外はプログラム自体で処理できますが、エラーは処理できません。

通常、Javaの例外(ExceptionやErrorを含む)は、チェック可能な例外(チェック例外)とチェックされない例外(未チェック例外)に分けられます。

チェック可能な例外(コンパイラが処理する必要がある例外):発生しやすく、正しいプログラムが実行されている場合には許容できる例外。チェック可能な例外は異常事態ではありますが、その発生はある程度予測可能であり、異常事態が発生した場合には何らかの対処が必要となります。

RuntimeExceptionとそのサブクラスを除き、他のExceptionクラスとそのサブクラスはチェック可能な例外です。この種の例外の特徴は、Java コンパイラがそれをチェックすることです。つまり、この種の例外がプログラム内で発生する可能性がある場合、try-catch ステートメントを使用してそれをキャッチするか、throws 句を使用して宣言します。そうしないとコンパイルが通りません。

チェック不可能な例外(コンパイラが強制処理を必要としない例外):実行時例外(RuntimeExceptionとそのサブクラス)とエラー(Error)が含まれます。

例外 この種の例外は、実行時例外と非実行時例外(コンパイル例外)の 2 つの主要なカテゴリに分類されます。プログラムはこれらの例外を可能な限り処理する必要があります。

ランタイム例外: NullPointerException (null ポインター例外)、IndexOutOfBoundsException (添字範囲外例外) など、RuntimeException クラスとそのサブクラスのすべての例外です。これらの例外はチェック例外ではありません。それらをプログラムで捕捉するか、対処しないでください。これらの例外は通常、プログラムの論理エラーによって発生するため、プログラムは論理的な観点からこのような例外の発生を回避するように努める必要があります。

実行時例外の特徴は、Javaコンパイラがチェックしないこと、つまり、プログラム内でこの種の例外が発生する可能性がある場合、たとえtry-catch文で捕捉されなくても宣言されないことです。 throws 句でスローすることもできます。これもコンパイルして渡されます。

非実行時例外(コンパイル例外):RuntimeException以外の例外であり、型的にはExceptionクラスとそのサブクラスに属します。プログラムの構文の観点からは、これは処理する必要がある例外であり、処理されない場合、プログラムはコンパイルされません。 IOException、SQLException など、およびユーザー定義の例外 通常、カスタムのチェック例外は必要ありません。

3. 例外処理の仕組み

Java アプリケーションにおける例外処理の仕組みは、例外をスローすることと、例外をキャッチすることです。

例外のスロー: メソッドでエラーが発生し、例外がスローされると、メソッドは例外オブジェクトを作成し、それをランタイム システムに渡します。例外オブジェクトには、例外の種類や実行時のプログラムのステータスなどの例外情報が含まれます。例外が発生します。ランタイム システムは、例外を処理するコードを見つけて実行する責任があります。

例外のキャッチ: メソッドが例外をスローした後、ランタイム システムは適切な例外ハンドラーを見つけます。潜在的な例外ハンドラーは、例外が発生したときに呼び出しスタックに順番に残るメソッドのコレクションです。例外ハンドラーが処理できる例外の種類が、メソッドによってスローされる例外の種類と一致する場合、それは適切な例外ハンドラーです。ランタイム システムは、例外が発生したメソッドから開始し、適切な例外ハンドラーを含むメソッドを見つけて実行するまで、コール スタック内のメソッドをチェックバックします。ランタイム システムがコール スタックを走査し、適切な例外ハンドラーが見つからない場合、ランタイム システムは終了します。それは同時にJavaプログラムの終了を意味します。

実行時例外、エラー、またはチェック可能な例外では、Java テクノロジーで必要とされる例外処理方法が異なります。

ランタイム例外はチェックできない性質があるため、アプリケーションをより合理的かつ簡単に実装するために、Java ではランタイム例外が Java ランタイム システムによって自動的にスローされ、アプリケーションがランタイム例外を無視できるようにすることが規定されています。

メソッドの実行中に発生する可能性のあるエラーについて、実行中のメソッドがそれをキャッチしたくない場合、Java ではメソッドがスロー ステートメントを作成しないようにします。なぜなら、ほとんどのエラー例外は決して発生してはいけない状況であり、合理的なアプリケーションがキャッチすべきではない例外だからです。

すべてのチェック可能な例外について、Java では、メソッドがそれをキャッチするか、メソッドの外でスローされるように宣言する必要があると規定しています。つまり、メソッドがチェック可能な例外をキャッチしないことを選択した場合、例外をスローすることを宣言する必要があります。

例外をキャッチできるメソッドは、対応する型の例外ハンドラーを提供する必要があります。キャプチャされた例外は、それ自体のステートメントによって引き起こされてスローされた例外である場合もあれば、呼び出されたメソッドまたは Java ランタイム システムによってスローされた例外である場合もあります。つまり、メソッドがキャッチできる例外は、どこかの Java コードによってスローされた例外である必要があります。簡単に言えば、例外は常に最初にスローされ、後でキャッチされます。

自分で書いたコード、Java 開発環境パッケージ、または Java ランタイム システムからのコードなど、あらゆる Java コードが例外をスローする可能性があります。誰でも Java の throw ステートメントを通じて例外をスローできます。

メソッドからスローされる例外は throws 節を使用する必要があります。

例外のキャッチは、try-catch ステートメントまたは try-catch-finally ステートメントによって実現されます。

一般に、Java では、チェック可能な例外はキャッチされるか、スローされると宣言される必要があると規定されています。チェックできない RuntimeException および Error を無視できるようにします。

  3.1 捕获异常:try、catch 和 finally

  1.try-catch语句

  在Java中,异常通过try-catch语句捕获。其一般语法形式为:

try { 
    // 可能会发生异常的程序代码 
} catch (Type1 id1){ 
    // 捕获并处置try抛出的异常类型Type1 
} 
catch (Type2 id2){ 
     //捕获并处置try抛出的异常类型Type2 
}

关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。

  匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。

  例1  捕捉throw语句抛出的“除数为0”异常。

public class TestException { 
    public static void main(String[] args) { 
        int a = 6; 
        int b = 0; 
        try { // try监控区域 
               
            if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常 
            System.out.println("a/b的值是:" + a / b); 
        } 
        catch (ArithmeticException e) { // catch捕捉异常 
            System.out.println("程序出现异常,变量b不能为0。"); 
        } 
        System.out.println("程序正常结束。"); 
    } 
}

  运行结果:

  程序出现异常,变量b不能为0。

  程序正常结束。

  例1  在try监控区域通过if语句进行判断,当“除数为0”的错误条件成立时引发ArithmeticException异常,创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器catch并运行相应异 常处理代码,打印输出“程序出现异常,变量b不能为0。”try-catch语句结束,继续程序流程。

  事实上,“除数为0”等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句。

  例2  捕捉运行时系统自动抛出“除数为0”引发的ArithmeticException异常。

public static void main(String[] args) { 
        int a = 6; 
        int b = 0; 
        try { 
            System.out.println("a/b的值是:" + a / b); 
        } catch (ArithmeticException e) { 
            System.out.println("程序出现异常,变量b不能为0。"); 
        } 
        System.out.println("程序正常结束。"); 
    } 
}

    运行结果:

  程序出现异常,变量b不能为0。

  程序正常结束。

  例2  中的语句:

  System.out.println(“a/b的值是:” + a/b);

  在运行中出现“除数为0”错误,引发ArithmeticException异常。运行时系统创建异常对象并抛出监控区域,转而匹配合适的异常处理器catch,并执行相应的异常处理代码。

  由于检查运行时异常的代价远大于捕捉异常所带来的益处,运行时异常不可查。Java编译器允许忽略运行时异常,一个方法可以既不捕捉,也不声明抛出运行时异常。

  例3  不捕捉、也不声明抛出运行时异常。

public class TestException { 
    public static void main(String[] args) { 
        int a, b; 
        a = 6; 
        b = 0; // 除数b 的值为0 
        System.out.println(a / b); 
    } 
}

    运行结果:

  Exception in thread “main” java.lang.ArithmeticException: / by zero
at Test.TestException.main(TestException.java:8)

  例4  程序可能存在除数为0异常和数组下标越界异常。

public class TestException { 
    public static void main(String[] args) { 
        int[] intArray = new int[3]; 
        try { 
            for (int i = 0; i <= intArray.length; i++) { 
                intArray[i] = i; 
                System.out.println("intArray[" + i + "] = " + intArray[i]); 
                System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值:  " 
                        + intArray[i] % (i - 2)); 
            } 
        } catch (ArrayIndexOutOfBoundsException e) { 
            System.out.println("intArray数组下标越界异常。"); 
        } catch (ArithmeticException e) { 
            System.out.println("除数为0异常。"); 
        } 
        System.out.println("程序正常结束。"); 
    } 
}

    运行结果:

  intArray[0] = 0

  intArray[0]模 -2的值:  0

  intArray[1] = 1

  intArray[1]模 -1的值:  0

  intArray[2] = 2

  除数为0异常。

  程序正常结束。

  例4  程序可能会出现除数为0异常,还可能会出现数组下标越界异常。程序运行过程中ArithmeticException异常类型是先行匹配的,因此执行相匹配的catch语句:

catch (ArithmeticException e){ 
      System.out.println("除数为0异常。"); 
 }

    需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。

  Java通过异常类描述异常类型,异常类的层次结构如图1所示。对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子 句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。

  RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。因此,RuntimeException异常类的catch子句应该放在 最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。

  2. try-catch-finally语句

  try-catch语句还可以包括第三部分,就是finally子句。它表示无论是否出现异常,都应当执行的内容。try-catch-finally语句的一般语法形式为:

try { 
    // 可能会发生异常的程序代码 
} catch (Type1 id1) { 
    // 捕获并处理try抛出的异常类型Type1 
} catch (Type2 id2) { 
    // 捕获并处理try抛出的异常类型Type2 
} finally { 
    // 无论是否发生异常,都将执行的语句块 
}

  例5  带finally子句的异常处理程序。

public class TestException { 
    public static void main(String args[]) { 
        int i = 0; 
        String greetings[] = { " Hello world !", " Hello World !! ", 
                " HELLO WORLD !!!" }; 
        while (i < 4) { 
            try { 
                // 特别注意循环控制变量i的设计,避免造成无限循环 
                System.out.println(greetings[i++]); 
            } catch (ArrayIndexOutOfBoundsException e) { 
                System.out.println("数组下标越界异常"); 
            } finally { 
                System.out.println("--------------------------"); 
            } 
        } 
    } 
}

    运行结果:

  Hello world !

  ————————–

  Hello World !!

  ————————–

  HELLO WORLD !!!

  ————————–

  数组下标越界异常

  ————————–

  在例5中,请特别注意try子句中语句块的设计,如果设计为如下,将会出现死循环。如果设计为:

try { 
      System.out.println (greetings[i]); i++; 
}

   小结:

  try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
  catch 块:用于处理try捕获到的异常。
  finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
  1)在finally语句块中发生了异常。
  2)在前面的代码中用了System.exit()退出程序。
  3)程序所在的线程死亡。
  4)关闭CPU。

  3. try-catch-finally 规则(异常处理语句的语法规则):

  1)  必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
  2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
  3) catch 块与相应的异常类的类型相关。
  4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
  5) 可嵌套 try-catch-finally 结构。
  6) 在 try-catch-finally 结构中,可重新抛出异常。
  7) 除了下列情况,总将执行 finally 做为结束:JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击。

  4. try、catch、finally语句块的执行顺序:

  1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;

  2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;

  3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

  图示try、catch、finally语句块的执行:

Java例外処理メカニズムの深い理解

3.2 抛出异常

  任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。从方法中抛出的任何异常都必须使用throws子句。

  1. throws抛出异常

  如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理。

  throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。throws语句的语法格式为:

methodname throws Exception1,Exception2,..,ExceptionN 
{ 
}

 方法名后的throws Exception1,Exception2,…,ExceptionN 为声明要抛出的异常列表。当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。例如:

import java.lang.Exception; 
public class TestException { 
    static void pop() throws NegativeArraySizeException { 
        // 定义方法并抛出NegativeArraySizeException异常 
        int[] arr = new int[-3]; // 创建数组 
    } 
   
    public static void main(String[] args) { // 主方法 
        try { // try语句处理异常信息 
            pop(); // 调用pop()方法 
        } catch (NegativeArraySizeException e) { 
            System.out.println("pop()方法抛出的异常");// 输出异常信息 
        } 
    } 
   
}

    使用throws关键字将异常抛给调用者后,如果调用者不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。

  pop方法没有处理异常NegativeArraySizeException,而是由main函数来处理。

  Throws抛出异常的规则:

  1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。

  2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误

  3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。

  4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。

  例如:

void method1() throws IOException{}  //合法   
   
//编译错误,必须捕获或声明抛出IOException   
void method2(){   
  method1();   
}   
    
//合法,声明抛出IOException   
void method3()throws IOException {   
  method1();   
}   
    
//合法,声明抛出Exception,IOException是Exception的子类   
void method4()throws Exception {   
  method1();   
}   
    
//合法,捕获IOException   
void method5(){   
 try{   
    method1();   
 }catch(IOException e){…}   
}   
    
//编译错误,必须捕获或声明抛出Exception   
void method6(){   
  try{   
    method1();   
  }catch(IOException e){throw new Exception();}   
}   
    
//合法,声明抛出Exception   
void method7()throws Exception{   
 try{   
  method1();   
 }catch(IOException e){throw new Exception();}   
}

    判断一个方法可能会出现异常的依据如下:

  1)方法中有throw语句。例如,以上method7()方法的catch代码块有throw语句。

  2)调用了其他方法,其他方法用throws子句声明抛出某种异常。例如,method3()方法调用了method1()方法,method1()方法声明抛出IOException,因此,在method3()方法中可能会出现IOException。

  2. 使用throw抛出异常

  throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。

  我们知道,异常是异常类的实例对象,我们可以创建异常类的实例对象通过throw语句抛出。该语句的语法格式为:

  throw new exceptionname;

  例如抛出一个IOException类的异常对象:

  throw new IOException;

  要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。下面的操作是错误的:

  throw new String(“exception”);

  这是因为String 不是Throwable 类的子类。

  如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。

  如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeException,则该方法的调用者可选择处理该异常。

package Test; 
import java.lang.Exception; 
public class TestException { 
    static int quotient(int x, int y) throws MyException { // 定义方法抛出异常 
        if (y < 0) { // 判断参数是否小于0 
            throw new MyException("除数不能是负数"); // 异常信息 
        } 
        return x/y; // 返回值 
    } 
    public static void main(String args[]) { // 主方法 
        int  a =3; 
        int  b =0;  
        try { // try语句包含可能发生异常的语句 
            int result = quotient(a, b); // 调用方法quotient() 
        } catch (MyException e) { // 处理自定义异常 
            System.out.println(e.getMessage()); // 输出异常信息 
        } catch (ArithmeticException e) { // 处理ArithmeticException异常 
            System.out.println("除数不能为0"); // 输出提示信息 
        } catch (Exception e) { // 处理其他异常 
            System.out.println("程序发生了其他的异常"); // 输出提示信息 
        } 
    } 
   
} 
class MyException extends Exception { // 创建自定义异常类 
    String message; // 定义String类型变量 
    public MyException(String ErrorMessagr) { // 父类方法 
        message = ErrorMessagr; 
    } 
   
    public String getMessage() { // 覆盖getMessage()方法 
        return message; 
    } 
}

    3.3 异常链

  1) 如果调用quotient(3,-1),将发生MyException异常,程序调转到catch (MyException e)代码块中执行;

  2) 如果调用quotient(5,0),将会因“除数为0”错误引发ArithmeticException异常,属于运行时异常类,由Java运行时系统自动抛出。quotient()方法没有捕捉ArithmeticException异常,Java运行时系统将沿方法调用栈查到main方法,将抛出的异常上传至quotient()方法的调用者:

  int result = quotient(a, b); // 调用方法quotient()

  由于该语句在try监控区域内,因此传回的“除数为0”的ArithmeticException异常由Java运行时系统抛出,并匹配catch子句:

catch (ArithmeticException e) { // 处理ArithmeticException异常
System.out.println(“除数不能为0″); // 输出提示信息
}

    处理结果是输出“除数不能为0”。Java这种向上传递异常信息的处理机制,形成异常链。

  Java方法抛出的可查异常将依据调用栈、沿着方法调用的层次结构一直传递到具备处理能力的调用方法,最高层次到main方法为止。如果异常传递到main方法,而main不具备处理能力,也没有通过throws声明抛出该异常,将可能出现编译错误。

  3)如还有其他异常发生,将使用catch (Exception e)捕捉异常。由于Exception是所有异常类的父类,如果将catch (Exception e)代码块放在其他两个代码块的前面,后面的代码块将永远得不到执行,就没有什么意义了,所以catch语句的顺序不可掉换。

  3.4 Throwable类中的常用方法

  注意:catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句”e.getMessage();”用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:

  getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。

  getMeage():返回异常的消息信息。

printStackTrace(): オブジェクトのスタック トレースがフィールド System.err の値としてエラー出力ストリームに出力されます。

わかりやすくするために、catch ステートメント以降のコードが無視されることがあります。そのため、try-catch ステートメントは、プログラムの実行中に例外が発生すると、例外処理が無視され、原因がわかります。エラーを見つけるのは困難です。

4. Java の一般的な例外

Java では、頻繁に発生するエラーを説明するためにいくつかの例外が用意されており、プログラマが例外をキャッチまたはスローするように宣言する必要があるものと、Java 仮想マシンによって自動的にキャッチされ処理されるものがあります。 Java の一般的な例外クラス:

1. runtimeException サブクラス:

1. java.lang.ArrayIndexOutOfBoundsException

配列インデックスの範囲外の例外。配列のインデックスが負の場合、または配列サイズ以上の場合にスローされます。

2. java.lang.ArithmeticException

算術条件例外。例: 整数のゼロ除算など。

3. java.lang.NullPointerException

Null ポインタ例外。この例外は、アプリケーションがオブジェクトが必要な場所で null を使用しようとするとスローされます。例: null オブジェクトのインスタンス メソッドの呼び出し、null オブジェクトのプロパティへのアクセス、null オブジェクトの長さの計算、throw ステートメントを使用した null のスローなど。 4. java.lang.ClassNotFoundException

クラス例外ではありません。見つかった。この例外は、アプリケーションが文字列形式のクラス名に基づいてクラスを構築しようとしたが、CLASSPAH を走査した後に対応する名前のクラス ファイルが見つからなかった場合にスローされます。

5. java.lang.NegativeArraySizeException 配列の長さが負です

6. java.lang.ArrayStoreException 配列に互換性のない値が含まれています

7. java.lang.SecurityException セキュリティ例外

8. java.lang.IllegalArgumentException 不正ですパラメータ例外

2.IOException

IOException: 入力ストリームおよび出力ストリームの操作時に発生する可能性のある例外。

EOFException ファイル終了例外

FileNotFoundException ファイルが見つからない例外

3. その他

ClassCastException 型変換例外クラス

ArrayStoreException 配列に互換性のない値が含まれる場合にスローされる例外

SQLException 操作データベース例外クラス

NoSuchFi eldException フィールドがありません見つかった例外

NoSuchMethodException メソッドが見つからない例外がスローされました

NumberFormatException 文字列を数値に変換することによってスローされた例外

StringIndexOutOfBoundsException 範囲外の文字列インデックスの例外がスローされました

IllegalAccessException 特定の種類の例外へのアクセスは許可されていません

InstantiationException Class クラスの newInstance() メソッドを使用してクラスのインスタンスを作成する場合、指定されたクラス オブジェクトがインスタンス化できない場合、この例外がスローされます

5. カスタム例外

Java の組み込み例外クラスを使用すると、ほとんどの例外について説明しますプログラミング中に起こること。さらに、ユーザーは例外をカスタマイズすることもできます。ユーザー定義の例外クラスは、Exception クラスを継承するだけで済みます。

プログラム内でカスタム例外クラスを使用するには、大きく次の手順に分かれます。

(1) カスタム例外クラスを作成します。

(2) メソッド内の throw キーワードを通じて例外オブジェクトをスローします。

(3) 現在例外をスローしているメソッドで例外が処理されている場合は、try-catch ステートメントを使用してそれをキャプチャして処理できます。それ以外の場合は、メソッドの宣言で throws キーワードを使用して、例外をスローすることを示します。メソッドの呼び出し元にスローされ、次のステップの操作に進みます。
(4) 例外メソッドの呼び出し元で例外をキャッチして処理します。

上記の「throwを使って例外をスローする」例でも触れました。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。