本記事は2006年に執筆されたものです。2011年の改訂版は以下の連載の第23回「プログラマの宿命! 例外とエラー処理を理解する」をご参照ください。
【改訂版】Eclipseではじめるプログラミング New!
これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipse 3.4とJava 6を使い大幅に情報量を増やした、連載「Eclipseではじめるプログラミング」の改訂版です
Javaではエラーへ対処する処理を記述するための仕組みとして例外というものがあります。データの入出力を伴うプログラムでは、基本的に例外を使ったプログラムを作成する必要がありますから、よく理解しておきましょう。また、この仕組みを使うとエラーへ対応するプログラムを書くのがとても簡単になりますから、自分が作成するクラスへも積極的に組み込めるようになりましょう。
プログラムでエラーが発生した場合の対処方法としては、どんな方法が考えられるでしょうか。単純なエラーに対応する場合には、メソッドの返却値を利用することができます。例えば、CenterFrameクラスを作成し、このクラスへデスクトップの幅と高さを受け取って、ウィンドウをデスクトップの中央に配置するlocateToCenterメソッドを作成したとします。この場合、デスクトップのサイズがウィンドウのサイズよりも小さい場合はエラーとして処理を行わないことにします。このとき、中央へ配置する処理が行われた場合は true を返し、エラーが発生した場合には false を返すことにします。
public class CenterFrame extends javax.swing.JFrame { public CenterFrame() { this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); } public boolean locateToCenter(int width, int height) { if (width <= getSize().width || height <= getSize().height) { return false; } setLocation((width-getSize().width)/2, (height-getSize().height)/2); return true; } }
このメソッドを使う場合には、次のCenterFrameMainクラスで行っているのと同じようにしてCenterFrameクラスのlocateToCenterメソッドを呼び出します。正常に処理が終了した場合は画面を表示しますが、エラーが発生した場合はエラーメッセージをコンソール画面へ出力して画面は表示しません。このようにlocateToCenterメソッドを使えば、メソッドの処理が正常に終了したのか、エラーが発生したのかを判定した処理が可能となります。
public class CenterFrameMain { public static void main(String[] args) { CenterFrame f = new CenterFrame(); f.setSize(800, 600); if (f.locateToCenter(1024, 768)) { f.setVisible(true); } else { System.out.println("Error"); } CenterFrame f2 = new CenterFrame(); f2.setSize(1600, 1200); if (f2.locateToCenter(1024, 768)) { f2.setVisible(true); } else { System.out.println("Error"); } } }
さてここで、CenterFrameクラスのlocateToCenterメソッドは正常終了したかどうかを返却するように定義できましたが、すべてのメソッドがこのようにできるわけではありません。このため、メソッドの返却値を使う方法には限界があります。例えば、デスクトップの中央へ画面を表示するための座標を取得できるメソッドを提供することになったとしたら、次のようなメソッドになるでしょう。
public java.awt.Point getPointForLocateToCenter(int width, int height) { if (width <= getSize().width || height <= getSize().height) { return null; } return new java.awt.Point( (width-getSize().width)/2, (height-getSize().height)/2); }
ここでは、返却値はjava.awt.Point型の座標なので、計算で問題が発生する場合にはnullを返すようにしています。これはつまり、このメソッドを使って取得した座標値を使う場合には、必ずnull判定をする必要があるということになり、エラー処理へ対応するためのコードが多くなるという問題につながります。これを避けるために、例えば(‐1, ‐1)という座標値を返却するようにメソッドを用意することもできますが、その場合はこのメソッドから返却される(‐1, ‐1)という座標値は特別な意味があるということをメソッドの使用者が知っている必要が出てきます。エラーの発生原因が1つしかないような単純な場合はこれでも良いのですが、「ファイルを開く」といった処理をしたときに、「指定したファイルがなくて開けなかった」のか「アクセス権がなくて開けなかった」のか「そのファイルを排他的に使っているプロセスがあるために開けなかった」のか、といったようにエラーを発生させる原因が複数ある場合にも対応しようとすると、メソッドを作成する側もメソッドを利用する側もかなり多くのチェックコードをコーディングする必要が出てきてしまいます。
ほかにもメソッドの返却値を使ったエラーの対処方法では、対応することが難しいことがあります。例えば、ハードウェアの故障などにより、即座にプログラムを停止する必要がある致命的なエラーが発生することはありますから、これに備えたプログラムの記述をプログラマへ強制させたいといった場合です。CenterFrameクラスのlocateToCenterメソッドについて、必ず成功か失敗かを判定するように強制したくても、次のようにプログラムがコーディングをした場合にコンパイラはエラーを出しません。ですから、判定の強制をプログラマにすることができません。この結果、プログラマのうっかりミスで、メソッドが返すエラーをチェックしないプログラムというのが簡単に入り込んでしまうわけです。
CenterFrame f = new CenterFrame(); f.setSize(800, 600); f.locateToCenter(1024, 768); f.setVisible(true);
Javaではこういった問題を解決するために、例外というメカニズムが用意されています。例外を使うと、メソッドがエラーコードを返したり、メソッドからのエラーコードをチェックしたりしなくても、メソッドの中でエラーが発生したことを簡単に捕捉して対応する処理を記述することができます。Javaには次の2種類の例外がありますので、順番に見ていきましょう。また、例外と深い関係にあるjava.lang.Errorクラスについても簡単に解説をします。
java.lang.RuntimeExceptionはjava.lang.Exceptionのサブクラスですから、クラス体系上で見ると「2種類の例外がある」というわけではありません。ただし、性質が大きく異なるため、本稿では分けて解説をしています。また、java.lang.Errorクラスはjava.lang.Exceptionクラスで表現される例外とは違いますが、java.lang.Errorとjava.lang.Exceptionはjava.lang.Throwableクラスをどちらも継承していますので、java.lang.Throwable型であるという点では同じであり深い関係があるといえます。
Copyright © ITmedia, Inc. All Rights Reserved.