例外処理

プログラミングの中でエラー処理は重要です。
プログラムは行いたいことを実現するための処理ですが、何かを実現する過程では外乱が発生する可能性があります。これらの外乱への対処がエラー処理です。ただ、このエラー処理をプログラマーがそれぞれ独自に行っていたら、プログラムの解読には手間がかかりプログラムの保守は大変です。
そこでJavaではプログラムの可読性を高めるため、行いたい処理とエラー処理を構造化して分離する仕組み「構造化例外処理」が用意されています

コンピュータで発生する不具合を総称してエラーと呼びましたが、、これには大きく分けて
実行環境のトラブルなど、プログラムでは対処できない不具合を表すエラー
プログラムで対処できる不具合を表す例外
の2つの種類があります。

Java言語では例外を、さらに検査例外と非検査例外に分けます。検査例外とは、処理中に例外が発生してもプログラム的な復旧が可能な処理に対して例外処理が記述されているかをコンパイラが検査する例外で、例外処理を書かないとコンパイルが通らず実行できない例外です。
もう一方の非検査例外は、例外が発生しないようにプログラム的な考慮が事前に可能な例外で、そのような考慮は行われる前提でコンパイラが検査しない例外です。

検査例外の例:FileNotFoundException

Cドライブ直下のdata.txtファイルを読み込むためのFileReaderインスタンスを作成する時に、FileNotFoundExceptionが発生した場合の例外処理をコメントアウトしてあります。

import java.io.FileNotFoundException;
import java.io.FileReader;

public class NoExceptionSample {

	public static void main(String[] args) {
//		try {
			FileReader reader = new FileReader("C:/data.txt");
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		}
	}
}

コンパイル結果

>javac ExceptionSample.java
ExceptionSample.java:4: エラー: クラスNoExceptionSampleはpublicであり、ファイルNoExceptionSample.javaで宣言する必要があります
public class NoExceptionSample {
       ^
エラー1個

>

例外処理のコメントを外せば、コンパイルは通ります。

非検査例外の例:ArithmeticException

除算を実行します。0による除算は実行できないので、事前にプログラム的な考慮がされていることを前提にコンパイラーは例外の発生可能性を検査しませんから、0による除算が行われることが確実でもコンパイルエラーは発生しません。
例ではArithmeticException(この場合は0による除算)に対する例外処理をコメントアウトしてあります。

import java.lang.ArithmeticException;

public class RuntimeExceptionSample {

	public static void main(String[] args) {
		int num = 10;
		int denum = 0;
		int ans;
		
//		try {
			ans = num / denum;
//		} catch (ArithmeticException e) {
//			System.out.println("0による除算を実行しました。");
//		}
	}
}

コンパイルはエラーを出さずに終了します。

>javac RuntimeExceptionSample.java

>

Javaでは、エラー及び全ての例外はThrowableクラスのサブクラスであり、各クラスの継承関係は以下のようになっています。
例外処理の必要性はクラスにより異なりますが、各クラス及び各クラスのサブクラスは例外処理によりcatchすることが出来ます

Object
Throwable
┣━Error(エラー)
例外処理の記述は可能。
┗━Exception(検査例外)
例外処理の記述は必須。
┗━RuntimeException(非検査例外)
例外処理の記述は可能。

構造化例外処理

ErrorとException