違反エラー制御

55936 ワード

異例のエラー制御はプログラムの作成に大きなメリットをもたらしました.
 1 public class test {
2 public static void f() throws Exception {
3 System.out.println(
4 "originating the exception in f()");
5 throw new Exception("thrown from f()");
6 }
7 public static void g() throws Throwable {
8 try {
9 f();
10 } catch(Exception e) {
11 System.out.println(
12 "Inside g(), e.printStackTrace()");
13 e.printStackTrace();
14 throw e;
15 }
16 }
17 public static void main(String[] args) throws Throwable {
18 try {
19 g();
20 } catch(Exception e) {
21 System.out.println(
22 "Caught in main, e.printStackTrace()");
23 e.printStackTrace();
24 }
25 }
26 }
output:
java.lang.Exception: thrown from f()

originating the exception in f()

Inside g(), e.printStackTrace()

	at test.f(test.java:5)

	at test.g(test.java:9)

	at test.main(test.java:21)

java.lang.Exception: thrown from f()

	at test.f(test.java:5)

	at test.g(test.java:9)

	at test.main(test.java:21)

Caught in main, e.printStackTrace()

違反経路スタックは、自分が何度「投げ」を繰り返しても、その本当の起点をどうしても覚えています.printStackTrace()はいつ実行されますか?なぜ異なる場合に出力の順序が異なるのですか?呼び出しレコードはいつ記録されますか?このプログラムからすべて見えます.もう1つの例で問題を説明します.
 1 public class test {
2 public static void f() throws Exception {
3 System.out.println(
4 "originating the exception in f()");
5 throw new Exception("thrown from f()");
6 }
7 public static void main(String[] args) {
8 try {
9 f();
10 } catch(Exception e) {
11 System.out.println(
12 "Caught in main, e.printStackTrace()");
13 e.printStackTrace();
14 throw new NullPointerException("from main");
15 }
16 }
17 }
output
originating the exception in f()

Caught in main, e.printStackTrace()

java.lang.Exception: thrown from f()

	at test.f(test.java:5)

	at test.main(test.java:9)

Exception in thread "main" java.lang.NullPointerException: from main

	at test.main(test.java:14)

異常と異常の間には名前の違いしかありません(だから名前が重要です).Throwableには、ExceptionとErrorの2つの一般的なタイプがあります.Errorはコンパイル期間とシステムエラーを指し、わざわざ彼らを捕まえる必要はありません.Exceptionは、任意の標準Javaライブラリのクラスメソッドから「throw」を出すことができる基本タイプです.RuntimeExceptionはデフォルトで自動的に処理されますが、RuntimeExceptionをチェックしなければならないと、私たちのコードはかなり複雑になります(時々空のポインタを押して自分で処理しなければなりませんか?)例:
 1 public class test {
2 static void f() {
3 throw new RuntimeException("From f()");
4 }
5 static void g() {
6 f();
7 }
8 public static void main(String[] args) {
9 g();
10 }
11 }
output
Exception in thread "main" java.lang.RuntimeException: From f()

	at test.f(test.java:3)

	at test.g(test.java:6)

	at test.main(test.java:9)

RuntimeExceptionがmain()に到達するすべてのルートを取得し、同時にキャプチャされない場合、プログラムは終了時にprintStackTrace()を自動的に呼び出す.
自分の「Exception」を作るのは簡単でしょう.例を挙げてみましょう.
 1 class MyException extends Exception {
2 public MyException() {}
3 public MyException(String msg) {
4 super(msg);
5 }
6 }
7 public class test {
8 public static void f() throws MyException {
9 System.out.println(
10 "Throwing MyException from f()");
11 throw new MyException();
12 }
13 public static void g() throws MyException {
14 System.out.println(
15 "Throwing MyException from g()");
16 throw new MyException("Originated in g()");
17 }
18 public static void main(String[] args) {
19 try {
20 f();
21 } catch(MyException e) {
22 e.printStackTrace();
23 }
24 try {
25 g();
26 } catch(MyException e) {
27 e.printStackTrace();
28 }
29 }
30 }
output
MyException

	at test.f(test.java:11)

	at test.main(test.java:20)

MyException: Originated in g()

	at test.g(test.java:16)

	at test.main(test.java:25)Throwing MyException from f()

Throwing MyException from g()


違反をどのように制限しますか?異常を捕まえたとき、私たちが捕まえたものが正しいことをどうやって知ったのですか.
 1 class BaseballException extends Exception {}
2 class Foul extends BaseballException {}
3 class Strike extends BaseballException {}
4 abstract class Inning {
5 Inning() throws BaseballException {}
6 void event () throws BaseballException {
7 }
8 abstract void atBat() throws Strike, Foul;
9 void walk() {}
10 }
11 class StormException extends Exception {}
12 class RainedOut extends StormException {}
13 class PopFoul extends Foul {}
14 interface Storm {
15 void event() throws RainedOut;
16 void rainHard() throws RainedOut;
17 }
18 public class test extends Inning implements Storm {
19 test() throws RainedOut, BaseballException {}
20 test(String s) throws Foul, BaseballException {}
21 public void rainHard() throws RainedOut {}
22 public void event() {}
23 void atBat() throws PopFoul {}
24 public static void main(String[] args) {
25 try {
26 test si = new test();
27 si.atBat();
28 } catch(PopFoul e) {
29 } catch(RainedOut e) {
30 } catch(BaseballException e) {
31 }
32 try {
33 Inning i = new test();
34 i.atBat();
35 } catch(Strike e) {
36 } catch(Foul e) {
37 } catch(RainedOut e) {
38 } catch(BaseballException e) {
39 }
40 }
41 }

Javaではfinallyで消去(例外から実行を再開する例でもあります):
 1 public class test {
2 static int count = 0;
3 public static void main(String[] args) {
4 while(true) {
5 try {
6 if(count++ == 0)
7 throw new Exception();
8 System.out.println("No exception");
9 } catch(Exception e) {
10 System.out.println("Exception thrown");
11 } finally {
12 System.out.println("in finally clause");
13 if(count == 2) break;
14 }
15 }
16 }
17 }
output
Exception thrown

in finally clause

No exception

in finally clause

finallyのコードは、どんな場合でも実行されます.finallyは何ができるの?たとえば、ファイルやソケットを開くときにfinallyでリソースを解放します.finallyがなければどうやって実現しますか?
 1 class Switch {
2 boolean state = false;
3 boolean read() { return state; }
4 void on() { state = true; }
5 void off() { state = false; }
6 }
7 public class test {
8 static Switch sw = new Switch();
9 public static void main(String[] args) {
10 try {
11 sw.on();
12 sw.off();
13 } catch(NullPointerException e) {
14 System.out.println("NullPointerException");
15 sw.off();
16 } catch(IllegalArgumentException e) {
17 System.out.println("IOException");
18 sw.off();
19 }
20 }
21 }

finallyの良さがうかがえるでしょう.異常が現在のcatchでキャプチャされていない場合でも、「finally」は、例外制御メカニズムがより高いレベルに移動してコントローラを検索する前に実行されます.eg:
 1 class Ex extends Exception {}
2 public class test {
3 public static void main(String[] args) {
4 System.out.println("Entering first try block");
5 try {
6 System.out.println("Entering second try block");
7 try {
8 throw new Ex();
9 } finally {
10 System.out.println("finally in 2nd try block");
11 }
12 } catch(Ex e) {
13 System.out.println("Caught Ex in first try block");
14 } finally {
15 System.out.println("finally in 1st try block");
16 }
17 }
18 }
output
Entering first try block

Entering second try block

finally in 2nd try block

Caught Ex in first try block

finally in 1st try block

Javaの異常制御メカニズムには欠陥があり、1つの異常が簡単に「破棄」される可能性があります.eg:
 1 class VeryImportantException extends Exception {
2 public String toString() {
3 return "A very important exception!";
4 }
5 }
6 class HoHumException extends Exception {
7 public String toString() {
8 return "A trivial exception";
9 }
10 }
11 public class test {
12 void f() throws VeryImportantException {
13 throw new VeryImportantException();
14 }
15 void dispose() throws HoHumException {
16 throw new HoHumException();
17 }
18 public static void main(String[] args)
19 throws Exception {
20 test lm = new test();
21 try {
22 lm.f();
23 } finally {
24 lm.dispose();
25 }
26 }
27 }
output
Exception in thread "main" A trivial exception

	at test.dispose(test.java:16)

	at test.main(test.java:24)

これで「try」ブロックの異常は無視され、出力される異常は「finally」モジュールのものとなる.コンストラクタのあるファイル、ソケットなどのリソースの解放を一例で見てみましょう(これは悪くないと思います):
 1 import java.io.*;
2 class InputFile {
3 private BufferedReader in;
4 InputFile(String fname) throws Exception {
5 try {
6 in = new BufferedReader(new FileReader(fname));
7 } catch(FileNotFoundException e) {
8 System.out.println("Could not open " + fname);
9 throw e;
10 } catch(Exception e) {
11 try {
12 in.close();
13 } catch(IOException e2) {
14 System.out.println("in.close() unsuccessful");
15 }
16 throw e;
17 } finally {}
18 }
19 String getLine() {
20 String s;
21 try {
22 s = in.readLine();
23 } catch(IOException e) {
24 System.out.println("readLine() unsuccessful");
25 s = "failed";
26 }
27 return s;
28 }
29 void cleanup() {
30 try {
31 in.close();
32 } catch(IOException e2) {
33 System.out.println("in.close() unsuccessful");
34 }
35 }
36 }
37 public class test {
38 public static void main(String[] args) {
39 try {
40 InputFile in = new InputFile("test.java");
41 String s;
42 int i = 1;
43 while((s = in.getLine()) != null)
44 System.out.println(""+ i++ + ": " + s);
45 in.cleanup();
46 } catch(Exception e) {
47 System.out.println("Caught in main, e.printStackTrace()");
48 e.printStackTrace();
49 }
50 }
51 }

異常で何ができるか:
  • 問題を解決し、異常を引き起こす方法を再び呼び出す.
  • 事態の発展を鎮め、再試行せずに継続する.
  • は、方法によって生成される結果ではなく、他の結果を計算する.
  • 現在の環境で可能な限り処理し、同じ異常をより高度な環境に再「throw」する.
  • プログラムの実行を終了する.
  • 簡略化コード;
  • は、自分のライブラリとプログラムをより安全にします.

  • -----------------------------
    個人的に理解して、レンガを撮ることを歓迎します.