1日目のゴール
1日目のテーマは
「例外ってそもそも何?」「try / catch って何をしているの?」を、感覚でつかむこと です。
今日は、こんな流れで進めます。
例外とは何か
なぜ try / catch が必要なのか
超シンプルな「割り算アプリ」で例外を体験する
異常系(うまくいかないケース)を“想定して書く”感覚を持つ
例外ってそもそも何者?
「普通じゃないことが起きた」ときの合図
Java でプログラムを書いていると、
「普通に進められない状況」が必ず出てきます。
存在しないファイルを開こうとした
0 で割り算しようとした
数字じゃない文字列を、整数に変換しようとした
こういうとき、Java は
「例外(Exception)」という“特別な出来事”を投げてきます。
「もうこのままは続けられないから、誰かこの状況を処理して!」
という“ヘルプの叫び”みたいなものです。
エラーと例外のざっくり違い
初心者のうちは、こう覚えておけばOKです。
コンパイルエラー
→ そもそも文法が間違っていて、プログラムが“始まる前に”止まる
例外(Exception)
→ 文法は正しいけど、“実行中に”問題が起きて止まる可能性があるもの
今日扱うのは、後者の「実行中のトラブル」です。
try / catch の役割を一言でいうと
「ここで失敗するかも」を囲っておく
try / catch は、ざっくり言うとこうです。
この中の処理は、失敗するかもしれない(try)
もし失敗したら、ここで受け止めてどうするか決める(catch)
形はこう。
try {
// 失敗するかもしれない処理
} catch (Exceptionの種類 e) {
// 失敗したときにやりたい処理
}
Javaポイントは二つです。
「どこが失敗するか」を自分で囲む
「失敗したときにどう振る舞うか」を自分で決める
これが「異常系対策」です。
例題:割り算ミニアプリで例外を体験する
作るもののイメージ
コンソールで動く、超シンプルな割り算アプリを作ります。
1つ目の数を入力
2つ目の数を入力
割り算して結果を表示
ここで、わざと「失敗しそうなケース」を考えます。
数字じゃない文字を入力したら?
0 で割ったら?
これを、try / catch で受け止めていきます。
まずは「例外なし」で書いてみる
import java.util.Scanner;
public class DivideApp {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("1つ目の整数を入力してください: ");
String aStr = scanner.nextLine();
System.out.print("2つ目の整数を入力してください: ");
String bStr = scanner.nextLine();
int a = Integer.parseInt(aStr);
int b = Integer.parseInt(bStr);
int result = a / b;
System.out.println("結果: " + result);
scanner.close();
}
}
Java一見、普通に見えますが、
このコードには“爆弾”が二つ埋まっています。
数字じゃない文字を入れると Integer.parseInt で例外
2つ目に 0 を入れると a / b で例外
実行して、わざとやってみると、
赤いエラーメッセージが出てプログラムが落ちます。
これが「例外が投げられて、誰も受け止めなかった状態」です。
NumberFormatException を try / catch で受け止める
「数字じゃない入力」を想定する
まずは、Integer.parseInt のところを守ります。
import java.util.Scanner;
public class DivideApp {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("1つ目の整数を入力してください: ");
String aStr = scanner.nextLine();
System.out.print("2つ目の整数を入力してください: ");
String bStr = scanner.nextLine();
try {
int a = Integer.parseInt(aStr);
int b = Integer.parseInt(bStr);
int result = a / b;
System.out.println("結果: " + result);
} catch (NumberFormatException e) {
System.out.println("整数として解釈できない入力があります。数字だけを入力してください。");
}
scanner.close();
}
}
Javaここでのポイントを分解します。
try { ... } の中に「失敗しそうな処理」をまとめたcatch (NumberFormatException e) で「数字じゃないとき」を受け止めた
例外が起きても、アプリが“落ちずに”メッセージを出して終われる
この時点で、
「変な入力が来ても、ユーザーにメッセージを返せるアプリ」になっています。
ArithmeticException(0で割った)も受け止める
0 で割ったときの例外
次に、a / b のところです。
2つ目の数に 0 を入れると、ArithmeticException: / by zero という例外が出ます。
これも try / catch で受け止められます。
複数の例外を別々に扱う
import java.util.Scanner;
public class DivideApp {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("1つ目の整数を入力してください: ");
String aStr = scanner.nextLine();
System.out.print("2つ目の整数を入力してください: ");
String bStr = scanner.nextLine();
try {
int a = Integer.parseInt(aStr);
int b = Integer.parseInt(bStr);
int result = a / b;
System.out.println("結果: " + result);
} catch (NumberFormatException e) {
System.out.println("整数として解釈できない入力があります。数字だけを入力してください。");
} catch (ArithmeticException e) {
System.out.println("0 で割ることはできません。2つ目の数には 0 以外を入力してください。");
}
scanner.close();
}
}
Javaここでの重要ポイントは二つです。
catch は複数書ける
例外の種類ごとに、メッセージや対応を変えられる
「何が起きたか」に応じて、
ユーザーへの説明を変えられるのが、例外処理の強みです。
どこまで try に含めるか、がすごく大事
try の“範囲”を意識する
初心者がよくやりがちなのが、
「とりあえず全部 try に突っ込む」パターンです。
try {
// なんでもかんでもここに入れる
} catch (Exception e) {
// とりあえずエラー
}
Javaこれは、
「どこで何が失敗したのか」が分かりにくくなるので、あまり良くありません。
今日の例でいうと、
「どこが失敗しそうか」をちゃんと意識して囲むのが大事です。
Integer.parseInt は NumberFormatException を投げるa / b は ArithmeticException を投げる
だから、その周辺だけを try に入れる、という考え方です。
例:範囲をもう少し細かくする
慣れてきたら、こんな書き方もできます。
int a;
int b;
try {
a = Integer.parseInt(aStr);
b = Integer.parseInt(bStr);
} catch (NumberFormatException e) {
System.out.println("整数として解釈できない入力があります。数字だけを入力してください。");
scanner.close();
return;
}
try {
int result = a / b;
System.out.println("結果: " + result);
} catch (ArithmeticException e) {
System.out.println("0 で割ることはできません。2つ目の数には 0 以外を入力してください。");
}
Javaこうすると、
「数字としておかしい」のと
「0 で割った」のが
コード上もきれいに分かれます。
1日目はここまでやらなくてもOKですが、
「try の範囲は、自分で設計するもの」
という感覚だけ持っておいてください。
finally という“最後に必ず実行される場所”
finally の役割
try / catch には、もうひとつ finally があります。
try {
// 失敗するかもしれない処理
} catch (Exception e) {
// 失敗したとき
} finally {
// 成功しても失敗しても、最後に必ず実行される
}
Java例えば、ファイルやネットワーク、Scanner などの
「開いたら閉じる必要があるもの」を扱うときに使います。
今回の例だと、scanner.close() を finally に入れるのが典型です。
Scanner scanner = new Scanner(System.in);
try {
// 入力を使った処理
} catch (Exception e) {
System.out.println("何かエラーが発生しました: " + e.getMessage());
} finally {
scanner.close();
}
Javaこれで、
途中で例外が起きても、
最後に必ず scanner.close() が呼ばれます。
1日目で絶対に押さえてほしい本質
今日いちばん大事なのは、
「例外は“悪いもの”ではなく、“異常を知らせる仕組み”だ」という感覚 です。
例外が投げられるのは、「想定外の状況が起きた」サイン
try / catch は「そのサインを受け取って、自分でどうするか決める場所」
異常系対策とは、「失敗しそうなところを先に想像して、try / catch で囲むこと」
そして、例題の割り算アプリで体験したように、
数字じゃない入力 → NumberFormatException
0 で割る → ArithmeticException
それぞれに対して、ユーザーに分かりやすいメッセージを返せる
ここまでイメージできたら、
もう「例外=よく分からない赤いエラー」ではなく、
「自分で扱える“出来事”」 になっています。
次のステップでは、
「例外を投げる側」「呼び出し元に伝える側」も含めて、
もう少し深く例外処理を設計していけます。
