今回は、例外処理を習いました。
予期せぬエラーが起きたときにする処理ということらしいっす。
Javaにおけるエラー
Javaでのエラーは大まかに、
- 文法エラー(syntax error)
- 実行時エラー(runtime error)
- 論理エラー(logic error)
の3つに分類できるようです。そのうち、例外処理は『2. 実行時エラー(runtime error)』に効果的のようです、というか『2. 実行時エラー(runtime error)』だけに注力する感じですかね?
『1. 文法エラー(syntax error)』に関しては、コンパイル時にエラーを出してくれるので、コンパイラーに丸投げしておいても大丈夫?かと。エディターのソースコード上でエラーが出るので気づきやすいエラーです。
package exceptionSample; public class SyntaxErrorSample { public static void main(String[] args) { // 『;』忘れでコンパイルエラーの例 System.out.println("『;』が記述されてない~!") } }
『3. 論理エラー(logic error)』に関しては、コンパイルエラー、実行時エラー、ともに起きないので、自力で不具合を起こしている個所を見つけねばなりません(地獄)。
package exceptionSample; public class LogicErrorSample { public static void main(String[] args) { int leftNumber = 3; int rightNumber = 5; // 本当は8と出力して欲しいが、空の『""』が邪魔してる System.out.println("合計" + leftNumber + "" + rightNumber); } }
『2. 実行時エラー(runtime error)』に関しては、コンパイルエラーは起こらないものの、実行時エラーが発生します。
package exceptionSample; public class RuntimeErrorSample { public static void main(String[] args) { String[] animals = {"孫悟空", "猪八戒", "沙悟浄", "牛魔王", "鉄扇公主", "紅孩児", "金角大王", "銀角大王"}; // コンパイルエラーは起きないけど、実行時エラーになる // 配列animalsは、0~7までの要素しかないのに、8番目にアクセスしようとしてエラー System.out.println(animals[8]); } }
例外処理の出番です
Javaで例外処理を実装する場合、
- try-catch文
- try-with-resources文
の2つが有名みたいです。
まずは、try-catch文
package exceptionSample; public class TryCatchSample { public static void main(String[] args) { // try-catch文 try { String str = null; System.out.println(str.length()); // ↓ エラーが起きたら処理 } catch (Exception e) { // エラー内容を表示 e.printStackTrace(); // ↑ エラーが起きた場合はここまでしか処理されない } // ↓ エラーが起きた場合は、表示されない System.out.println("END"); } }
実行すると、
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8 at exceptionSample.RuntimeErrorSample.main(RuntimeErrorSample.java:9)
というエラーが表示されますが、try句の中でエラーが起きた場合、catch句に処理が移るためです。e.printStackTrace()が実行されると処理は終了します。
もう一つ、try-catch文。Eclipseで「Javaプロジェクト」>「src」の上で右クリックし、「新規」>「フォルダ」で『file』というフォルダを作って、
その中に『data.txt』ファイルを作成しておきます。
「パッケージ・エクスプローラー」の構成が下記のようになります。
『data.txt』の上で右クリックし、「プロパティ」を選択します。
「ロケーション(L):」のほうのパスを使用します。
package exceptionSample; import java.io.FileWriter; import java.io.IOException; public class TryCatchSample { public static void main(String[] args) { // FileWriter fw = null; try { fw = new FileWriter("C:\\workspace\\ExceptionSample\\src\\file\\data.txt"); fw.write("abcabc"); } catch(IOException e) { e.printStackTrace(); } finally { try { fw.close(); } catch (IOException e) { // e.printStackTrace(); } } System.out.println("書き込みました。"); } }
続いて、try-withs-resources文。
package exceptionSample; import java.io.FileWriter; import java.io.IOException; public class TryWithResourcesSample { public static void main(String[] args) { // try(FileWriter fw = new FileWriter("C:\\workspace\\ExceptionSample\\src\\file\\data.txt");) { fw.write("efgefg"); } catch(IOException e) { e.printStackTrace(); } System.out.println("書き込みました。"); } }
try-with-resources文を使うと、FileWriterクラスのインスタンスをclose()しなくても、自動でclose()してくれるみたいです。finally句が省略できます。
⇩ 下記サイトが詳しいです
・【Java】try-catch文でfinallyを省略する【try−with−resource構文】 - 8t's BBR
例外処理を先送りにすることもできます。
package exceptionSample; public class ExceptionSendSample { public static void main(String[] args) { // try { sub(); } catch (Exception e) { // e.printStackTrace(); } } public static void sub() throws Exception { subsub(); } public static void subsub() throws Exception { String s = null; System.out.println(s.length()); } }
本当は、subsub()メソッド内でtry-catchすべきですが、メソッドにthrows Exceptionをつけることで、呼び出し元のsub()に任せた、となり、sub()にもthrows Exceptionをつけると、main()メソッドに任せたとなるようです。
最後まで、throws Exceptionをつけると、Exceptionクラスにすべて任せるということになります。
自分で独自に例外クラスを作成して利用することもできます。
public class MyExceptionSample extends Exception { public MyExceptionSample(String msg) { super(msg); } }
public class Main { public static void main(String[] args) { try{ // throw new MyExceptionSample("自分で作った例外クラス"); } catch(Exception e) { System.out.println(e); } } }
例外処理もどれを使っていくべきか判断が難しいですね。
今回はこのへんで。