Java入門|14章のまとめ

予想外のエラーにも落ち着いて向き合い、外の世界とつながる力を身につける章

この章では、Javaプログラムをもっと実用的にするための大切な力を学びました。
ひとつは、実行中に起こるトラブルに対応する例外処理です。
もうひとつは、画面、キーボード、ファイルなどとデータをやり取りする入出力処理です。

これまでの学習では、変数や条件分岐、繰り返し、配列、クラスといった、プログラムの土台になる考え方を順番に身につけてきました。
14章では、その土台の上に、さらに一歩進んで「実際に使えるプログラムらしさ」を加える内容を学んだといえます。

ドラゴンボールの世界でたとえるなら、これまでの章で技の出し方や戦い方、仲間の役割を学んできて、この章では
「想定外の攻撃にどう対応するか」
「修行記録や戦闘データをどう受け取り、どう残すか」
を学んだようなものです。
強い技を持っているだけでは十分ではなく、トラブルに対処できて、必要な情報をきちんと扱えることが、実戦ではとても大切ですよね。

ここでは、14章で学んだ内容を整理しながら、それぞれがどんな意味を持っているのかをやわらかく振り返っていきます。

例外処理は、予想外の出来事に備えるしくみ

Javaのプログラムは、いつも理想どおりに動くとは限りません。
配列の範囲をこえてしまったり、数値に変換できない文字が入ってきたり、ファイルが見つからなかったりすることがあります。
こうした実行中に起こる問題に対応するためのしくみが、例外処理でした。

まず押さえたいのは、例外は単なる失敗ではなく、Javaが異常を知らせるための合図だということです。
プログラムが「このままでは処理を続けられません」と判断したとき、例外が発生します。

ドラゴンボールの世界でいえば、修行中に重力装置の設定が危険な値になったとき、警報が鳴るようなものです。
その警報を無視して進むのではなく、受け止めて対応する必要があります。
それが例外処理の考え方でした。

try、catch、finally の役割

例外処理の基本として学んだのが、try、catch、finally の3つのブロックです。

それぞれの役割を整理すると、次のようになります。

ブロック役割
try例外が起こるかもしれない処理を書く
catch例外が起きたときに受け止めて処理する
finally例外の有無に関係なく最後に必ず行う処理を書く

この3つは、それぞれ担当がはっきり分かれています。

try は、まず処理を実行する場所です。
catch は、問題が起きたときの対応役です。
finally は、後片付けや終了処理の担当です。

ドラゴンボール風にすると、try は修行そのもの、catch はトラブル発生時に現場を立て直す仲間、finally は最後に修行室の装置を停止したり記録庫を閉じたりする係のようなものです。

この考え方を理解すると、プログラムは「エラーが起きたら終わり」ではなく、
エラーを受け止めながら最後まで丁寧に動かせるものになっていきます。

例外はクラスとして存在している

14章では、例外の正体がクラスのオブジェクトであることも学びました。
ここはとても大切なポイントです。

例外は、ただの文字列メッセージではありません。
Throwable を親にもつクラスから作られたオブジェクトです。
そして catch の丸かっこの中では、その例外オブジェクトを変数で受け取っていました。

たとえば、配列の範囲外アクセスで起きる ArrayIndexOutOfBoundsException も、例外クラスのひとつです。
catch の中で変数を使って例外情報を表示できたのは、そこにきちんとしたオブジェクトが渡ってきていたからです。

これは、Javaのオブジェクト指向らしい見方でもあります。
ドラゴンボールでいえば、「事件」や「トラブル」とひとまとめにするのではなく、
「サイヤ人の異常事態」
「修行装置の異常」
「入力データの異常」
のように、種類ごとに系統立てて整理されている感覚です。
例外も、クラスの継承関係の中に位置づけられているからこそ、種類ごとの処理ができるわけです。

独自の例外クラスを作れる意味

Javaでは、用意されている例外を使うだけでなく、自分で独自の例外クラスを作れることも学びました。
これを行うには、Throwable のサブクラスを継承して新しい例外クラスを作ります。
学習では Exception を継承する形が分かりやすい基本でした。

これは、クラス設計の立場から見るととても重要です。
なぜなら、自分が作ったクラスに対して
「この状態は特別な異常です」
と、意味のある名前を付けて利用者へ伝えられるからです。

ドラゴンボールでたとえるなら、ただ「危険」と言うだけでなく、
「重力修行設定エラー」
「スカウター読み取り異常」
のように、異常の種類をはっきり区別して警報を出せるようにする感じです。

こうすると、クラスを使う人も
「このメソッドでは、こういう異常が起こる可能性があるんだな」
と理解しやすくなります。

throw と throws の意味

14章では、例外を受け取るだけでなく、自分で送出することも学びました。
ここで大事だったのが throw と throws の違いです。

書き方意味
throw例外オブジェクトを実際に送出する
throwsそのメソッドが例外を送出する可能性があると宣言する

throw は、その場で実際に例外を投げる動作です。
throws は、そのメソッドの説明として「この例外が起こるかもしれません」と示すものです。

この違いが分かると、例外処理の流れがとても見えやすくなります。
クラスの設計者は、異常な状態が見つかったときに throw を使って警報を出し、利用者には throws でその可能性を伝えます。

ドラゴンボールの世界でいうと、throw は実際に警報ボタンを押すこと、throws は「この修行室では条件によって警報が鳴ります」と入口に書いておくことに近いです。

例外を処理するか、上へまかせるか

例外が送出される可能性のあるメソッドを使うときには、基本的に2つの選択肢がありました。

選択肢内容
その場で処理するtry-catch を使って自分で受け止める
上へまかせるthrows を付けて呼び出し元へ処理を渡す

これは、クラス設計と利用の両方に関わる大事な考え方です。
設計者がすべてを内部で処理してしまうと、利用者が柔軟に使えないことがあります。
逆に、利用者に任せることで、場面に応じた対応が可能になります。

ドラゴンボール風にたとえるなら、現場の悟空がその場で対応するか、界王様や仲間へ判断を上げるか、という役割分担に似ています。
いつもひとつの対応しかないのではなく、状況に合わせて選べるのが大切です。

明示的な例外処理が不要な例外もある

14章では、すべての例外に同じように try-catch や throws が必要なわけではないことも学びました。
特に、Error のサブクラスや RuntimeException のサブクラスは、明示的な例外処理を必ずしも要求しません。

これには理由があります。

Error は、プログラムの継続が難しいような致命的な問題を表すことが多いです。
RuntimeException は、配列の範囲外アクセスのように、まずはコードの書き方や使い方を見直すべき性質のものが多いです。

つまり、Javaは例外の種類ごとに
「利用者へ対応を強く求めるもの」
「そうではないもの」
を分けて考えています。

ここが見えてくると、例外処理がだいぶ整理されます。
すべてを同じ重さで見るのではなく、例外クラスの位置づけによって扱い方が変わるのです。

入出力はストリームで考える

14章のもうひとつの大きな柱が、入出力処理でした。
ここで中心になる考え方が、ストリームです。

ストリームは、データの流れを表す抽象的なしくみです。
画面、キーボード、ファイルといった相手が違っても、Javaではそれらを「データが流れる通り道」として統一的に扱います。

この考え方があるおかげで、

  • キーボードから入力する
  • 画面へ出力する
  • ファイルへ保存する
  • ファイルから読み込む

といった処理を、共通した感覚で理解できるようになります。

ドラゴンボールの世界でいえば、相手が地球でもナメック星でも界王星でも、気の流れとしてとらえることで状況を統一的に見られるようなものです。
Javaのストリームも、それとよく似た考え方です。

画面・キーボード・ファイルの入出力

14章では、まずキーボードから文字列を読み込み、画面へ表示する基本を学びました。
そこでは、標準入力である System.in と、標準出力である System.out を扱いました。

さらに、文字を読み込むために InputStreamReader や BufferedReader を使いました。
ここから、入出力では複数のクラスを組み合わせて使うことが多いと分かってきます。

その次に、ファイルへの書き込みと、ファイルからの読み込みを学びました。
ファイル出力では FileWriter、BufferedWriter、PrintWriter を組み合わせて、1行ずつデータを書き込みました。
ファイル入力では FileReader と BufferedReader を使って、1行ずつ readLine で読み込みました。

ここで大切なのは、相手がキーボードからファイルへ変わっても、考え方の土台は同じだということです。
ストリームを組み合わせてデータを流し、必要な形で取り出す
これが入出力の共通した基本でした。

close の大切さ

ファイルを扱うときに忘れてはいけないのが、close でした。
ファイルは開いただけでは終わらず、使い終わったら必ず閉じる必要があります。

これは、書き込みを確定させたり、読み込みを終えたり、使っていた資源を解放したりするために必要です。
finally の話ともつながりますが、こうした後片付けはとても大事です。

ドラゴンボール風にいえば、修行室を使い終わったら扉を閉め、記録庫を使い終わったら巻物を戻して保管を完了するようなものです。
途中の派手な処理だけでなく、最後をきちんと締めることが大切だと分かります。

ファイルを使うと実用性が大きく広がる

ファイル入出力を学んだことで、プログラムは一気に実用的になりました。
画面に表示するだけでは、その場で終わってしまいます。
でもファイルを使えば、データを残し、あとで読み返し、大量の情報を扱えるようになります。

たとえば、修行記録、戦闘力データ、設定値、結果の保存など、現実的なプログラムに欠かせないことができるようになります。

ドラゴンボールの世界でも、その場の会話だけでは修行内容は消えてしまいますが、記録として残しておけば次の判断に生かせます。
Javaのファイル入出力も、それと同じです。
情報を未来へつなぐための技術だといえます。

コマンドライン引数で外から値を受け取る

14章の最後では、コマンドライン引数も学びました。
これは、プログラムを実行するときに外から文字列を渡し、その値をプログラムの処理に利用するしくみです。

main メソッドの

String[] args

が、その受け皿でした。

args[0]、args[1] のように配列として扱えるので、ファイル名やメッセージなどを実行時に自由に指定できます。
さらに args.length を使えば、引数の個数も調べられます。

このしくみを使うと、ファイル名をソースコードに固定しなくてもよくなります。
同じプログラムを、実行時に別の引数を渡しながら何度も使えるようになります。

ドラゴンボール風にたとえるなら、修行装置を毎回作り替えるのではなく、起動時に
「今日はこの修行記録を読む」
「今日はこの設定で動かす」
と外から指示を渡す感覚です。
こうなると、プログラムはずっと柔軟で使いやすい道具になります。

14章で身についたことを整理する

14章で学んだことを、役割ごとに整理すると次のようになります。

テーマ学んだこと
例外処理try、catch、finally を使って異常時にも対応できる
例外クラス例外は Throwable 系列のクラスのオブジェクトである
独自例外自分で例外クラスを作れる
送出throw で例外を送り、throws で送出の可能性を宣言する
ストリーム入出力はデータの流れとして統一的に扱う
標準入出力画面やキーボードとのやり取りができる
ファイル入出力保存や読み込みによって実用的な処理ができる
コマンドライン引数実行時に値を受け取り、柔軟なプログラムを作れる

こうして並べてみると、14章は「トラブル対応」と「外部とのやり取り」という、実用的なプログラムに欠かせない2本柱を扱っていたことがよく分かります。

図で14章全体の流れを整理する

この図は、14章の内容を 例外処理入出力処理 の2つの大きなテーマに分けて整理したものです。
左側では、try、catch、finally、throw、throws、独自例外といった「異常にどう対応するか」がまとまりとして見えてきます。
右側では、ストリーム、標準入力・標準出力、ファイル入力・出力、コマンドライン引数といった「外部とどうデータをやり取りするか」がひとつながりで見えてきます。

この図から分かるのは、14章が単に細かな文法を学ぶ章ではなく、
予想外の事態への備え現実のデータとのやり取り を学ぶ章だった、ということです。
プログラムをより実践的にするための要素が、ここで一気にそろってきたことがよく分かります。

14章で得た力の意味

14章を学ぶ前と後では、プログラムに対する見方がかなり変わってきます。
以前は、書いた処理を順番に実行することが中心でした。
でもこの章を通して、

  • 想定外の事態が起きることを前提に考える
  • 外からデータを受け取る
  • 外へデータを残す
  • 利用者が使いやすい形で動かす

という視点が加わりました。

これは、プログラムが「学習用の小さな例」から「現実で使える形」へ近づいたということです。

ドラゴンボールでたとえるなら、ただ技を出せるだけではなく、
戦況の変化に対応し、仲間と情報をやり取りし、修行の記録を残し、次の戦いへ備えられるようになった状態です。
それだけ、14章で学んだ内容は実践的で大事なものだったといえます。