ホームページ >Java >&#&チュートリアル >Java例外とエラー処理の基本的な知識
例外とエラー:
例外: Java におけるプログラム エラーは、主に、プログラムのコンパイルおよび実行時に発生するエラーと総称され、VM (仮想マシン) によって通知されます。つまり、VM は、あなた (開発者) が間違いを犯し、それを修正する機会があることを知らせます。例外クラスは Java で例外を表すために使用され、異なる例外クラスは異なる例外を表します。ただし、Java のすべての例外には、Exception と呼ばれる基本クラスがあります。
エラー: 適切なアプリケーションでは阻止できない深刻な問題を指します。ほとんどが異常です。エラーは VM の障害です (ただし、システム レベルのサービスであればどのようなものでも発生する可能性があります)。したがって、エラーの処理は難しく、平均的な開発者 (もちろんあなたではありません) はメモリ オーバーフローなどのエラーを処理できません。 例外と同様、エラー クラスは Java でエラーを表すために使用され、異なるエラー クラスは異なるエラーを表します。 ただし、Java のすべてのエラーには、Error という基本クラスがあります。
要約すると、例外とエラーの最も本質的な違いは、例外は開発者が処理できるのに対し、エラーはシステムに固有のものであり、通常は処理できず、プログラマーが処理する必要がないということです。
1. 例外は、通常の命令の実行を中断する、プログラムの実行中に発生するイベントです。
許容されるコード動作から逸脱するアクションまたはインスタンスです。実行時例外 (チェックされていない例外)
2. コンパイル時例外 (チェックされた例外)
実行中の例外は RuntimeException、残りはすべてコンパイル例外です
Java の例外とエラー Error は共通の親クラス Throwable を持ちます。
エラー例外
runtimeException いくつかのサブクラス
1. java.lang.ArrayIndexOutOfBoundsException
配列インデックスの範囲外の例外。配列のインデックスが負の場合、または配列サイズ以上の場合にスローされます。
2. java.lang.ArithmeticException
算術条件例外。例: 整数のゼロ除算など。
3. java.lang.NullPointerException
Null ポインタ例外。この例外は、アプリケーションがオブジェクトが必要な場所で null を使用しようとするとスローされます。例: null オブジェクトのインスタンス メソッドの呼び出し、null オブジェクトの
属性へのアクセス、null オブジェクトの長さの計算、null をスローする throw ステートメントの使用など。
4. java.lang.ClassNotFoundException
クラス例外見つかりません。この例外は、アプリケーションが文字列形式のクラス名に基づいてクラスを構築しようとしたが、CLASSPAH を走査した後に対応する名前のクラス ファイルが見つからなかった場合にスローされます。
例外処理:
try{}catch{}
try{}catch{}finally{} 例外の有無に関係なく、finally コード ブロックが実行されます
try{}finally{} を組み合わせて使用することもできますただし、最終的にはキャッチします。{}いいえ
注: 継承関係では、サブクラスは親クラスのメソッドをオーバーライドし、例外をスローする範囲を親クラスより広くすることはできません
例外の使用
この部分は、例外の使用は主にデモンストレーション コードであり、コードを書く過程で通常遭遇するもの (もちろんごく一部) ですが、それは良いアイデアでしょうか?
例 1. この例では、主に 2 つのメソッドを比較することにより、例外が発生した後のコードの実行フローを示します。
public static void testException1() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("异常出现前"); try { System.out.println(ints[4]); System.out.println("我还有幸执行到吗");// 发生异常以后,后面的代码不能被执行 } catch (IndexOutOfBoundsException e) { System.out.println("数组越界错误"); } System.out.println("异常出现后"); } /*output: 异常出现前 数组越界错误 常出现后 */ 代码如下 复制代码 public static void testException2() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("异常出现前"); System.out.println(ints[4]); System.out.println("我还有幸执行到吗");// 发生异常以后,他后面的代码不能被执行 }
public class Rethrow { public static void readFile(String file) throws FileNotFoundException { try { BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); System.err.println("不知道如何处理该异常或者根本不想处理它,但是不做处理又不合适,这是重新抛出异常交给上一级处理"); //重新抛出异常 throw e; } } public static void printFile(String file) { try { readFile(file); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) { printFile("D:/file"); } }
例外の目的は良いものですが、実際には修復できる可能性は非常に低く、エラー情報を記録するために使用されることがよくあります。常に例外を処理することにうんざりしている場合は、例外を再スローすることで軽減される場合があります。この例外を変更せずに上位レベル、つまりこのメソッドを呼び出す人にスローし、彼に考えてもらいます。この観点から見ると、Java 例外 (もちろんチェック例外のことを指します) は、その出発点は良いものですが、私たちに多くの問題を引き起こしました。
ExceptionA,ExceptionB,ExceptionC public class ExceptionA extends Exception { public ExceptionA(String str) { super(); } } public class ExceptionB extends ExceptionA { public ExceptionB(String str) { super(str); } } public class ExceptionC extends ExceptionA { public ExceptionC(String str) { super(str); } }
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:19) */なぜ ExceptionC だけが出力され、ExceptionB は出力されないのでしょうか?これを自分で分析してみましょう!
上記の状況は例外を見逃すことと同等であり、トラブルシューティング プロセスにおいて非常に不利です。では、上記の状況に遭遇した場合はどうすればよいでしょうか?ここで例外チェーンが登場します。例外情報を保存することで、元の例外を失うことなく別の例外をスローできるようになります。
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); //异常连 c.initCause(e); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:21) Caused by: exception.ExceptionB at exception.NeverCaught.f(NeverCaught.java:5) at exception.NeverCaught.g(NeverCaught.java:10) ... 1 more */
这个异常链的特性是所有异常均具备的,因为这个initCause()方法是从Throwable继承的。
例4. 清理工作
清理工作对于我们来说是必不可少的,因为如果一些消耗资源的操作,比如IO,JDBC。如果我们用完以后没有及时正确的关闭,那后果会很严重,这意味着内存泄露。异常的出现要求我们必须设计一种机制不论什么情况下,资源都能及时正确的清理。这就是finally。
public void readFile(String file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(file))); // do some other work } catch (FileNotFoundException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
例子非常的简单,是一个读取文件的例子。这样的例子在JDBC操作中也非常的常见。(所以,我觉得对于资源的及时正确清理是一个程序员的基本素质之一。)
Try...finally结构也是保证资源正确关闭的一个手段。如果你不清楚代码执行过程中会发生什么异常情况会导致资源不能得到清理,那么你就用try对这段"可疑"代码进行包装,然后在finally中进行资源的清理。举一个例子:
public void readFile() { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work //close reader reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
我们注意一下这个方法和上一个方法的区别,下一个人可能习惯更好一点,及早的关闭reader。但是往往事与愿违,因为在reader.close()以前异常随时可能发生,这样的代码结构不能预防任何异常的出现。因为程序会在异常出现的地方跳出,后面的代码不能执行(这在上面应经用实例证明过)。这时我们就可以用try...finally来改造:
public void readFile() { BufferedReader reader = null; try { try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work // close reader } finally { reader.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
及早的关闭资源是一种良好的行为,因为时间越长你忘记关闭的可能性越大。这样在配合上try...finally就保证万无一失了(不要嫌麻烦,java就是这么中规中矩)。
再说一种情况,假如我想在构造方法中打开一个文件或者创建一个JDBC连接,因为我们要在其他的方法中使用这个资源,所以不能在构造方法中及早的将这个资源关闭。那我们是不是就没辙了呢?答案是否定的。看一下下面的例子:
public class ResourceInConstructor { BufferedReader reader = null; public ResourceInConstructor() { try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(""))); } catch (FileNotFoundException e) { e.printStackTrace(); } } public void readFile() { try { while(reader.readLine()!=null) { //do some work } } catch (IOException e) { e.printStackTrace(); } } public void dispose() { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
这一部分讲的多了一点,但是异常确实是看起来容易用起来难的东西呀,java中还是有好多的东西需要深挖的
更多java异常与错误处理基本知识相关文章请关注PHP中文网!