はじめに
このようなコードを書いたことはありますか?また、これを見て違和感を感じませんか??
public int ExeptionExample(Object obj) throws IllegalArgumentException {
if(obj instanceof Integer) {
try {
return (Integer)obj;
} catch (Exception e) {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
}
これは、実際に筆者が書いてしまったコードの一部です。これに何も感じないなら、本記事を読み、例外処理への理解を深めましょう。
Javaを学び始めると、避けても通れないが例外処理です。しかし、例外処理って自分で書くことが少ないと思います。最近のエディターやIDEはとても親切かつ優秀で、勝手にtry-catchを作ったり、throws宣言をしてくれたりしますよね。
筆者は大学、大学院でそこそこプログラミングを学び、2025年より新卒エンジニアとなりましたが、文明の利器に頼りきりだったため、実際に自分で例外処理を書くとき、まともに書けず、レビューで指摘をくらいまくりました。それが前述のコードです。
そこでこの記事では例外処理の基礎であるthrow,throws,try-catchの使い方を簡単にまとめます。
それと、甲子園がちょうど盛り上がっているので少し野球ネタも挟みつつ理解を深めます。
throw, throws, try-catchについて
例外処理でよく使われる3つの構文について、それぞれの役割を説明します。ついでに野球の守備に例えて補足します。理解の一助になれば幸いです。
throw
throwは、意図的に例外を発生させるキーワードです。例外を「発生させる」ことにより、プログラムの動きを止めます。
public class ThrowExample {
public static void main(String[] args) {
int age = -1;
if (age < 0) {
throw new IllegalArgumentException("年齢は0以上でなければなりません");
}
}
}
ここでは、変数ageが0より小さい時、「年齢が不正」という例外をIllegalArgumentExeceptionとしてthrowしています。
このように、ある処理を行うとき、条件によって非検査例外を意図的に発生させる場合に記述します。(検査例外、非検査例外についてはこちらの記事で非常にわかりやすく解説されています。)
野球でいうと
打球を捕球したショートがthrow先を選べます。セカンドがフォースアウト行けそうならセカンド、無理そうならファーストにthrowする、そんな感じだと思います。
throws
throwsは例外を投げる可能性を示す宣言です。例えば、メソッドを呼び出すとき、「このメソッドはこの例外を投げる可能性があります」と宣言します。
public class ThrowsExample {
public static void main(String[] args) throws Exception {
doSomething();
}
public static void doSomething() throws SQLException, NullPointerExeption {
// 何らかの処理
}
}
少々簡素ですが、この例ではdoSomething()がSQLExceptionもしくはNullPointerExceptionを投げる可能性があると宣言しています。mainは内部的に、その可能性を考慮しながら処理を実行します。なぜthrows宣言が必要なのかは、別記事で書こうと思います。
野球でいうと
1アウト1塁3塁で守備についているショートがセカンドにthrowする可能性もあるし、ホームにthrowする可能性もあります。打球速度や3塁ランナーの動き等(つまり、処理の結果)を見て判断しますよね。そういうことです。
try-catch
投げられた例外を受け止めて処理を継続したい(決まった処理を行いたい)ときに使います。try句の中には「例外が発生しうる処理」を書きます。
最近のエディターやIDEは、try-catchで囲うべき箇所を上手くサジェストしてくれますよね。
public class TryCatchExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // ここで例外が発生
} catch (ArithmeticException e) {
System.out.println("0で割ることはできません");
}
}
}
この例では、10 / 0で例外が発生しますが、処理がcatch句に進み、メッセージを出力させることができます。
野球でいうと
すみません。いい例が思いつきませんでした。ネタ切れです。
まとめ
- throw:意図的に例外を発生させる
- throws:発生しうる例外を宣言する
- try-catch:投げられた例外を受け止めて処理する
おわりに
例外処理では全部よくみますが、意味がわかってないと適切な例外処理を実装できません。コードが想定通りに動くように実装するのは大事ですが、例外が起きたときにそれを適切に処理することも同じくらい大事だと思います。
筆者の理解がまだまだ浅い可能性もあるので、間違いなどありましたらご指摘いただけると幸いです。また、野球に関してもっと良い例えがあれば教えて下さい。自分の頭ではこれが限界でした。
最後まで読んでいただきありがとうございました。