Javaのメソッドオーバーライドにおける例外処理のルールとは?
Javaでスーパークラスのメソッドをオーバーライドする際には、例外の扱いに関して従うべきルールがいくつかあります。本記事では、これらのルールを具体的なコード例とともにわかりやすく解説します。
ルール1:同じ例外、またはそのサブタイプをスローできる
スーパークラスのメソッドが特定の例外をスローする場合、サブクラスでオーバーライドされたメソッドは、同じ例外またはそのサブタイプ(派生クラス)をスローしなければなりません。
例:サブタイプの例外をスローする場合
次の例では、スーパークラスの readFile() メソッドが IOException をスローし、サブクラスの readFile() メソッドが FileNotFoundException をスローしています。FileNotFoundException は IOException のサブタイプであるため、このプログラムはエラーなくコンパイル・実行できます。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public String readFile(String path) throws IOException {
throw new IOException();
}
}
public class ExceptionsExample extends Super {
@Override
public String readFile(String path) throws FileNotFoundException {
Scanner sc = new Scanner(new File("E://test//sample.txt"));
String input;
StringBuffer sb = new StringBuffer();
while (sc.hasNextLine()) {
input = sc.nextLine();
sb.append(" "+input);
}
return sb.toString();
}
public static void main(String args[]) {
String path = "E://test//sample.txt";
ExceptionsExample obj = new ExceptionsExample();
try {
System.out.println(obj.readFile(path));
}catch(FileNotFoundException e) {
System.out.println("Make sure the specified file exists");
}
}
}
実行結果
ファイル「sample.txt」の内容が読み込まれ、標準出力に表示されます。なお、指定したファイルが存在しない場合は catch ブロックにより「Make sure the specified file exists」というメッセージが表示されます。
例:同じ例外をスローする場合
同様に、サブクラスがスーパークラスとまったく同じ例外をスローする場合も、プログラムは問題なくコンパイル・実行されます。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public void sampleMethod()throws FileNotFoundException {
System.out.println("Method of superclass");
}
}
public class ExceptionsExample extends Super {
public void sampleMethod()throws FileNotFoundException {
System.out.println("Method of Subclass");
}
public static void main(String args[]) {
ExceptionsExample obj = new ExceptionsExample();
obj.sampleMethod();
}
}
実行結果
Method of Subclass
ルール2:スーパータイプの例外はスローできない
スーパークラスのメソッドが特定の例外をスローする場合、サブクラスのメソッドがそのスーパータイプ(親クラス)の例外をスローすることは許されません。
例
次の例では、スーパークラスの readFile() メソッドが FileNotFoundException をスローしている一方で、サブクラスの readFile() メソッドは、そのスーパータイプにあたる IOException をスローしようとしています。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public String readFile(String path)throws FileNotFoundException {
throw new FileNotFoundException();
}
}
public class ExceptionsExample extends Super {
@Override
public String readFile(String path)throws IOException {
//method body ......
}
}
コンパイル時エラー
このプログラムをコンパイルすると、次のようなエラーが発生します。
ExceptionsExample.java:13: error: readFile(String) in ExceptionsExample cannot override readFile(String) in Sup
public String readFile(String path)throws IOException {
^
overridden method does not throw IOException
1 error
ルール3:例外をスローしないオーバーライドも可能
スーパークラスのメソッドが例外をスローしている場合でも、サブクラスでオーバーライドする際に例外を一切スローしないようにすることができます。
例
次の例では、スーパークラスの sampleMethod() メソッドは FileNotFoundException をスローしますが、サブクラスの sampleMethod() メソッドは例外をまったくスローしていません。それにもかかわらず、このプログラムはエラーなくコンパイル・実行されます。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public void sampleMethod()throws FileNotFoundException {
System.out.println("Method of superclass");
}
}
public class ExceptionsExample extends Super {
public void sampleMethod() {
System.out.println("Method of Subclass");
}
public static void main(String args[]) {
ExceptionsExample obj = new ExceptionsExample();
obj.sampleMethod();
}
}
実行結果
Method of Subclass
まとめ
オーバーライド時の例外処理のルールを整理すると、次のようになります。
- スーパークラスと同じ例外、またはそのサブタイプをスローできる
- スーパータイプの例外をスローするとコンパイルエラーになる
- 例外をまったくスローしないオーバーライドも有効
これらのルールは、ポリモーフィズムを利用する際に、呼び出し側がスーパークラスの宣言に基づいて例外を正しく捕捉できるようにするために設計されています。オーバーライド時に例外の範囲を広げてしまうと、呼び出し元が想定していない例外が発生する可能性があるためです。
-
JavaのString intern()メソッドとは?その役割と使い方をわかりやすく解説
JavaにおけるStringクラスの基本Stringは、Javaで一連の文字(文字列)を格納するためのクラスで、java.langパッケージに属しています。Stringオブジェクトは一度生成すると内容を変更できない「イミュータブル(不変)」という特性を持っています。文字列の保存場所すべてのStringオブジェクトは、ヒープ領域内にある「文字列定数プール(String Constant Pool)」と呼ばれる専用のメモリ領域に格納されます。文字列リテラルを定義するたびに、JVMは文字列定数プール内にその値を持つStringオブジェクトを生成します。そのため、同じ内容の文字列リテラルが複数存在して
-
Javaのpaint()メソッドとrepaint()メソッドの違いをわかりやすく解説
JavaでGUIアプリケーションを開発する際、コンポーネントの描画に関わるpaint()メソッドとrepaint()メソッドは、役割がまったく異なる重要なメソッドです。この記事では、両者の違いと正しい使い方を具体例とともに解説します。 paint()メソッドとrepaint()メソッドの違い paint()メソッドとは paint()は、コンポーネントを実際に描画するための処理(描画命令)を記述するメソッドです。Java AWTでは、このメソッドをオーバーライドして独自の描画処理を実装します。 一方、Java SwingではpaintComponent()メソッドをオーバーライドするのが推奨さ