Javaプログラミングをするうえで、例外処理「try-catch」は欠かせない重要な構文です。例外(エラー)を適切に処理しないと、プログラムが途中で止まってしまったり、思わぬバグの原因になったりすることがあります。
この記事では、Javaの例外処理「try-catch」の基本的な使い方を初心者にもわかりやすく解説します。また、例外処理を学ぶのに役立つおすすめの講座もご紹介するので、基礎から実践的なスキルまでをしっかり身につけられるでしょう。
Javaの例外処理を理解し、より安全でエラーに強いプログラム作りに役立ててください。
Javaの例外処理とは
Javaの例外処理とは、プログラムの実行中に発生するエラー(例外)を適切に処理し、システムの異常終了を防ぐ仕組みです。例外には、ゼロ除算や配列の範囲外アクセスなどによる実行時エラー、ファイルの読み書き失敗エラーなどがあります。
Javaでは、この例外処理のために「try-catch」構文が用意されています。tryブロックで例外が発生しうる処理を記述し、catchブロックでエラー時の対処を記述します。また、finallyブロックを使うことで、例外の有無にかかわらず必ず実行したい処理を記述することも可能です。
適切な例外処理を行うことで、プログラムの予期しない停止を防ぎ、より信頼性の高いコードを書くことができます。
なぜ例外処理が必要なのか
プログラムは、常に理想的な条件で動作するとは限りません。例えばユーザーがWebフォームに誤ったファイル名を入力した場合、ファイルの読み込みエラーが発生し、後続の処理が止まってしまう可能性があります。
こうしたリスクを回避するために重要なのが、例外処理です。例外処理を適切に行うことで、エラーが発生しても適切な対応が可能となり、プログラムの安定性を保てます。
上記の例なら、該当するファイルが見つからなかった場合に「ファイルが存在しません」とユーザーに知らせることで、後続の処理が止まるのを防げます。また、システムエラーが発生した際にエラーログを記録すれば、後のデバッグが容易になります。
このように、例外処理はプログラムの信頼性を高め、安定した動作を保証するために不可欠な仕組みと言えます。
エラーとバグの違い
プログラミング初心者の多くが混同しやすいのが、「エラー」と「バグ」の違いです。どちらもプログラムが正常に動作しない原因となりますが、意味は大きく異なります。
エラー(Error)とは、プログラムの実行中に発生する問題であり、多くの場合に例外処理(try-catch)を使った対処が可能です。一方、バグ(Bug)は、プログラムの設計やコードのミスによって発生する意図しない動作を言います。
大きな違いは、エラーは適切に処理すれば回避できますが、バグはコードの修正が必要であるという点です。両者の違いを表にまとめてみましょう。
項目 | エラー(Error) | バグ(Bug) |
---|---|---|
定義 | プログラム実行中に発生する問題 | コードの設計や実装ミスによる誤動作 |
原因 | 入力ミス、外部要因、リソース不足など | ロジックの誤り、変数の間違い、処理漏れなど |
発生タイミング | 実行時(ランタイムエラー) | 実行時・コンパイル時 |
例 |
|
|
対応方法 | try-catchを使った例外処理 | コードの修正 |
影響範囲 | プログラムがクラッシュ・強制終了する可能性あり | 意図しない動作や誤った結果を引き起こす |
このようにエラーとバグにはさまざまな違いがあるので、両者を正しく理解し、適切な例外処理を行うことが重要です。
Javaプログラミングの基礎をもっと詳しく知りたい方は、こちらもチェックしてください!
try-catchの基本構造と使い方
プログラムがエラーを起こさず正しく動作するためには、例外を適切に処理することが重要です。ここでは、Javaのtry-catchの基本構造や書き方、実際のコード例を交えてわかりやすく解説します。
try-catchの基本構造
Javaのtry-catchの基本構造は次のようになっています。
try {
// 例外が発生する可能性がある処理
} catch (例外の型 変数名) {
// 例外発生時の処理
}
ポイントは、例外が発生する可能性がある処理をtry{}で囲むことにあります。もし例外が発生した場合、catchで特定の例外を受け取り、適切な処理を行うことが可能です。これにより、例外が発生してもプログラムが異常終了せず、次の処理へ進められます。
try-catchのコード例と解説
Javaのtry-catch文の実際の使い方をコード例で見てみましょう。
public static void main(String[] args) {
try {
int result = 10 / 0; // ゼロ除算による例外発生
System.out.println(“計算結果: ” + result);
} catch (ArithmeticException e) {
System.out.println(“エラー発生: ゼロで割ることはできません”);
}
System.out.println(“プログラム終了”);
}
}
エラー発生: ゼロで割ることはできません
プログラム終了
サンプルコードは、整数の割り算を行って結果を出力するというものですが、実際にはゼロ除算(ゼロで割る=コンピューター上では実行不能と解釈される)によって例外(ArithmeticException)が発生しているケースです。catchブロックで例外を受け取り、エラーメッセージを表示した後でプログラムを終了しています。
try-catch-finallyの違いと使い分け
try-catchにfinallyを組み合わせることで、例外の有無に関係なく必ず実行したい処理を記述できます。ここでは、try-catch-finallyの違いや、それぞれの適切な使い分けについて詳しく解説します。
finallyの役割
finallyブロックは、例外の発生に関係なく、必ず実行される処理を記述するための構文です。基本構文を見てみましょう。
try {
// 例外が発生する可能性がある処理
} catch (例外の型 変数名) {
// 例外発生時の処理
} finally {
// 例外の有無に関わらず必ず実行する処理
}
プログラムでファイルやデータベースの接続を開いた場合、例外が発生しても適切にリソースを解放しなければなりません。finallyブロックを使えば、エラーが起こっても確実に close()メソッドを実行できるため、リソースの無駄な占有やメモリリークを防ぐことができます。
また、returnで値を返す必要があるような場面では、プログラムの後処理としてfinallyを活用するのが適切です。
try-with-resourcesを使った例外処理
try-with-resources構文は、Java7以降で導入された機能で、AutoCloseableインターフェースを実装したリソースを自動的にクローズできる仕組みです。これにより、finallyを使わなくても、リソースの後処理を確実に行うことができます。
サンプルコードを見てみましょう。
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader(“test.txt”))) {
String line = br.readLine();
System.out.println(“読み込んだ内容: ” + line);
} catch (IOException e) {
System.out.println(“エラー発生: ” + e.getMessage());
}
}
}
例では、BufferedReaderを使用して「test.txt」というファイルの内容を1行読み込み、表示する処理を行っています。try-with-resourcesを使用しているため、BufferedReaderはtry{}を抜けた時点で自動的にclose()されているのがポイントです。これにより、finallyブロックでclose()を呼び出す必要がなくなり、コードがシンプルになります。
また、ファイルの読み込み中にIOExceptionが発生する可能性があるため、catchブロックでエラーメッセージを出力し、プログラムの異常終了を防いでいます。
比較のため、同じ処理を従来のtry-catch-finally構文で記述してみましょう。try-with-resourcesの記述の簡潔さがよく分かるはずです。
import java.io.FileReader;
import java.io.IOException;
public class TryCatchFinallyExample {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(“test.txt”));
String line = br.readLine();
System.out.println(“読み込んだ内容: ” + line);
} catch (IOException e) {
System.out.println(“エラー発生: ” + e.getMessage());
} finally {
if (br != null) {
try {
br.close(); // リソースを明示的にクローズ
} catch (IOException e) {
System.out.println(“リソースを閉じる際にエラーが発生しました: ” + e.getMessage());
}
}
}
}
}
例外の伝播とthrow・throwsの違い
Javaでは、「例外の伝播」やthrow・throwsという仕組みがあります。ここでは、例外の伝播の仕組みと、throw・throwsの違いをわかりやすく解説しましす
例外の伝播とは
Javaにおいて、メソッド内で発生した例外を、呼び出し元のメソッドへ自動的に伝える仕組みを「例外の伝播」といいます。これにより、個々のメソッド内で例外を処理するのではなく、上位のメソッドでまとめて例外処理を行うことが可能です。
通常、メソッド内で例外が発生すると、そのメソッドが処理できない場合は呼び出し元へ例外が投げられます。これが繰り返され、最終的にmainメソッドまで例外が伝播し、適切に処理されなければプログラムは異常終了します。
この仕組みを理解した上で、適切な場所でtry-catchを用いて例外処理を行うことが大切です。
throwの使い方
throwは、プログラム内で任意の例外を発生させるためのキーワードです。
サンプルコードを見てみましょう。
public static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException(“18歳未満の方は利用できません”);
}
System.out.println(“年齢確認完了。利用可能です。”);
}
public static void main(String[] args) {
try {
validateAge(16); // 例外が発生
} catch (IllegalArgumentException e) {
System.out.println(“エラー: ” + e.getMessage());
}
}
}
上記の例では、validateAgeメソッド内でthrowを使用し、年齢が18歳未満の場合にIllegalArgumentExceptionを投げています。このように、throwを使うことで条件に応じて意図的に例外を発生させ、異常な状態を適切に通知することが可能です。
throwsの使い方
throwsは、メソッドが特定の例外をスローする可能性があることを宣言するためのキーワードです。サンプルコードを見てみましょう。
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
// ファイルを読み込むメソッド(例外をスロー)
public static void readFile(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
System.out.println(“ファイルの内容: ” + br.readLine());
br.close();
}
public static void main(String[] args) {
try {
readFile(“test.txt”); // 例外が発生する可能性がある
} catch (IOException e) {
System.out.println(“エラー: ファイルを読み込めませんでした – ” + e.getMessage());
}
}
}
上記の例では、readFileメソッドがIOExceptionを投げる可能性があるため、throwsキーワードを使って、その例外をメソッドの呼び出し元に伝えています。このようにthrowsを使うことで、メソッド内で例外を処理せず、呼び出し元でまとめて処理することが可能です。
throw・throwsの違い
これまで紹介してきたように、throw と throws はどちらも例外に関係するキーワードですが、役割が異なります。それぞれの違いを表で比較してみましょう。
項目 | throw | throws |
---|---|---|
役割 | 例外を発生させる | 例外が発生する可能性を宣言する |
使う場所 | メソッドの中 | メソッドのシグネチャ(定義部分) |
使い方 | throw new 例外クラス(“メッセージ”) | throws 例外クラス |
例 | throw new IllegalArgumentException(“不正な値です”); | public void readFile() throws IOException { … } |
処理の流れ | その場で即座に例外がスローされる | 例外が発生した場合、呼び出し元へ伝播する |
同時に指定できる例外の数 | 1つのみ | 複数の例外をカンマ区切りで指定可能 (throws IOException, SQLException ) |
このように、throwとthrowsの役割はそれぞれ異なるため、適切に使い分けることが重要です。
Javaの主要な例外と発生しやすいエラー
Javaでは、プログラムの実行中にさまざまな種類の例外が発生する可能性があります。ここでは、Javaの主要な例外の種類や、特に初心者がよく遭遇するエラーについて詳しく解説します。
チェック例外と非チェック例外の違い
Javaの例外は、「チェック例外(Checked Exception)」と「非チェック例外(Unchecked Exception)」の2種類に分類できます。それぞれの違いを表にまとめてみましょう。
名称 | 特徴 | 例 | 用途・考え方 |
---|---|---|---|
チェック例外(Checked Exception) |
|
| 基本的に「回避できない」 → 事前に対応策を考える必要がある |
非チェック例外(Unchecked Exception) |
|
| 基本的に「回避できる」→ プログラムの修正で防げるものが多い |
チェック例外は「予測可能なエラー」で、開発者が適切に処理する必要があります。一方、非チェック例外は「バグ由来のエラー」で、コードの修正によって防ぐべきものです。基本的には、外部リソースに関連する例外はチェック例外、コードの問題で起こるものは非チェック例外として扱います。
よくある例外の種類
Javaの開発で特によく遭遇する例外を、発生原因と対処法とあわせてまとめたものが次の表になります。
例外名 | 発生原因 | 主な対処法 |
---|---|---|
NullPointerException | nullのオブジェクトに対してメソッドを呼び出した | 変数がnullでないか事前にチェックする |
ArrayIndexOutOfBoundsException | 配列の範囲外のインデックスを指定した | 配列の長さを確認してからアクセスする |
ArithmeticException | 0で除算した | 除算前に0でないか確認する |
ClassCastException | 不適切な型キャストを行った | instanceofを使って型を確認する |
NumberFormatException | 文字列を数値に変換できなかった | 入力値が数値かどうかを事前に検証する |
IOException | ファイルが見つからない、読み込めない | try-catchで処理し、ファイルの存在を事前に確認する |
SQLException | データベース接続エラーやSQL文の誤り | try-catchで処理し、SQL文を検証する |
InterruptedException | スレッドの処理が割り込まれた | try-catchで処理し、スレッドを適切に管理する |
このような例外の種類と対処法を理解し、エラーに強いプログラムを作れるようになりましょう。
Javaの例外処理で意識するべきポイント
例外処理はプログラムの安定性を向上させるために重要ですが、間違った書き方をすると、かえってバグの原因になったり、デバッグが難しくなったりすることがあります。ここでは、Javaの例外処理で初心者が特に意識するべき重要なポイントを紹介します。
例外の種類ごとにcatchする
例外処理を記述する場合には、例外の種類ごとにcatchを分けて書くことで、エラーの原因を明確にし、適切なエラーハンドリングが可能になります。
例えば、次のコードを見てみましょう。
public static void main(String[] args) {
try {
int num = Integer.parseInt(“abc”); // 数値変換エラー発生
int result = 10 / 0; // ゼロ除算エラー発生(このコードには到達しない)
} catch (Exception e) {
System.out.println(“予期しないエラーが発生しました – ” + e.getMessage());
}
System.out.println(“プログラム終了”);
}
}
例外がすべてExceptionに集約されており、何のエラーが発生したか特定しにくいです。
では、同じ処理を次のように記述してみるとどうでしょう。
public static void main(String[] args) {
try {
int num = Integer.parseInt(“abc”); // 数値変換エラー発生
int result = 10 / 0; // ゼロ除算エラー発生(このコードには到達しない)
} catch (NumberFormatException e) {
System.out.println(“エラー: 数値に変換できません – ” + e.getMessage());
} catch (ArithmeticException e) {
System.out.println(“エラー: ゼロで割ることはできません – ” + e.getMessage());
} catch (Exception e) {
System.out.println(“予期しないエラーが発生しました – ” + e.getMessage());
}
System.out.println(“プログラム終了”);
}
}
こちらの例では、catchを細かく指定して記述することで、どのような例外が発生する可能性があるかが一目で分かるようになっていますね。また、発生した例外の種類に応じて適切なメッセージを出せています。
このように例外は適切に分類し、必要に応じて複数のcatchブロックを使うことで、プログラムの可読性と保守性を向上させ、より安全なエラーハンドリングを実現できるのです。
例外メッセージ(ログ)は具体的に出力する
例外が発生した際に適切なログを出力することは、エラーの原因を特定しやすくし、デバッグや運用保守をスムーズに行うために重要です。しかし、初心者がやりがちなミスとして、例外メッセージを曖昧に出力したり、エラーの詳細情報を記録しないケースがあります。
例えば、次のようなコードでは、例外が発生しても「エラーが発生しました」というメッセージしか出力されず、何が原因で問題が起こったのか分かりません。
System.out.println(“エラーが発生しました”);
}
このような書き方では、エラーの原因を特定するためにコードを一つずつ確認する必要があり、デバッグの手間が増えてしまいます。
そこで利用すべきなのが、e.getMessage()やe.printStackTrace()です。例を見てみましょう。
System.err.println(“ファイル読み込みエラー: ” + e.getMessage());
e.printStackTrace(); // スタックトレースを出力
}
このように書くことで、発生した例外の内容をより詳しく記録できます。
なお、開発現場ではログファイルにエラーを記録することが一般的です。JDK標準のロギング機能として「java.util.logging」が提供されていますが、近年ではSpring Bootなどのフレームワークを採用する現場が増え、「SLF4J + Logback」が標準のロギング手法となっています。
Javaのtry-catchも学べるおすすめ講座3選
Javaの例外処理を深く理解し、実践的に学ぶためには、オンライン講座を活用するのも効果的です。ここでは、Javaのtry-catchを含む例外処理を学べるおすすめの講座をご紹介します。
Progate
Progateは、初心者向けのオンラインプログラミング学習サービスで、スライド形式の解説と実際にコードを書きながら学べます。ブラウザ上でコードを実行できるため、環境構築不要で手軽に学習を始められるのが大きなメリットです。
Javaに関するさまざまなコースが用意されており、初心者から実践的な内容まで幅広く学ぶことができます。try-catchを含む例外処理についても学べるため、基礎から応用までしっかり習得したい人におすすめです。
Udemy
Udemyは、一度購入すれば無期限で視聴できる買い切り型のオンライン学習プラットフォームです。月額制のサブスクリプションとは異なり、自分のペースで学習を進められるのが特徴です。
初心者向けの基礎講座からSpring Boot を使ったWeb開発、Androidアプリ開発、試験対策講座 まで、Javaに関するさまざまなコースが提供されています。頻繁にセールが行われており、数万円の講座が1,000円台で購入できることもあるため、コストを抑えて学びたい人にもおすすめです。
忍者CODE
忍者CODEは、実践的なカリキュラムでJavaを学べるオンライン学習サービスです。基礎から応用まで体系的に学べるだけでなく、実務に近い環境で開発スキルを習得できます。
Javaコースでは環境構築なしで手軽に学習開始できるほか、動画教材+課題でしっかり理解でき、実務レベルの開発スキルを身につけられます。初心者でも無理なく学習を進められる内容になっているため、基礎を固めつつ、実務に役立つスキルも身につけたい人におすすめです。
就職におすすめのプログラミングセミナーについては、こちらもチェックしてください。
Javaのtry-catchで安全なコードを書く習慣を身につけよう
例外処理は、プログラムの安定性を保ち、予期しないエラーからシステムを守るために欠かせない要素です。Javaでtry-catchを適切に活用すれば、プログラムの異常終了を防ぎ、エラーを適切に処理できます。
Javaの例外処理を深く理解するには、実際にコードを書いて試しながら学ぶことが効果的です。書籍やオンライン教材、講座などを活用し、基礎から応用までしっかり学んでいきましょう。
