連載
» 2006年05月11日 00時00分 公開

デバッグのヒント教えます(1):Javaプログラムにおけるデバッグのパターンは?

[中越智哉,ナレッジエックス]

 時の過ぎるのは早いもので、年が明けたと思っていたら、気が付けばもう5月になってしまいました。新社会人の皆さんであればこれからエンジニアの仲間入りをしていろいろな知識を習得していこうと張り切っていらっしゃることでしょう。

 この連載ではJavaエンジニアの皆さんが必ずぶつかるデバッグについて実例を挙げながらその具体的な対処法について解説していきます。コンパイルエラーのメッセージは、現在よく使われているEclipse 3.1.x(の「問題」ビュー)で表示されるメッセージを基本に解説していきます。コンパイルに用いるJDKのバージョンは、5.0を想定しています。

Javaプログラムにおけるデバッグのパターンは?

 Javaプログラムにおけるデバッグの対象となりうるものには、大きく3つのパターンがあります。

 (1)コンパイルエラー
 (2)ランタイムエラー
 (3)仕様どおり動かない

(1)コンパイルエラー

 Javaのプログラムを書いていて最初にやるデバッグは、おそらくコンパイルエラーのデバッグではないでしょうか。コンパイルエラーとは文字通りプログラムをコンパイルしたときに発生するエラーで、プログラムの文法的な誤りを示してくれるものです。

 コンパイルエラーが存在しているプログラムは実行することができません(実行してもコンパイルエラーが解消されていないというメッセージが出て実行できない)。そのためコンパイルエラーは実行前にすべて取り除いておかなければなりません。

(2)ランタイムエラー

 ランタイムエラーとはこれも文字通り実行時(ランタイム)に発生するエラーです。文法は正しく、「コンパイルエラー」も発生しないプログラムをいざ実行してみると、実行途中に例外が発生してしまう、というケースがこれに当たります。プログラムの中には、値の内容を自在に変えることのできる「変数」や、プログラム自身では完全には管理できない外部と連携する処理などを書くことがあります。コンパイル時には、これらについては基本的に、「正しい値がセットされている」「外部要因は正しく動作している」という前提の下に解析を行っているために、実際、実行してみると値が正しくなかったり、外部のシステムがうまく動いていなかったりするケースも当然あります。

 ランタイムエラーの場合も、コンピュータのコード実行時に発見され、コードのどの部分でどのような異常な動作になったかが例外のスタックトレースなどで指摘されます。ですから、コンパイルエラーと同じく、修正は意外とたやすいように思えてしまいそうですが、実際には、それほど簡単な作業ではありません。あるプログラムにおいて、なぜその変数に異常な値が代入されたのか、どうして外部システムとの連携がうまくいかないのか、といった、エラーに至るまでの原因をコードを見たり、環境を調査したりしながら細かく分析していかなければいけないことが多いからです。

(3)仕様どおり動かない

 コンパイルエラー、ランタイムエラーは、エラーメッセージや例外のスタックトレースのように通知が行われますので、その見方さえ知っていれば、修正個所や原因の特定を比較的簡単に行うことができます。それらに対して、「仕様どおり動かない」パターンのデバッグは、少々厄介なものです。まず、「仕様どおり動かない」ことは、コンパイラや実行環境は指摘してくれません。どのように動作すれば「仕様どおり」であり、どのように動作すれば「仕様どおりでない」かは、コンパイラや実行環境は判断できないからです。このケースのデバッグに対処するためには、デバッガーを使ったり、コードを机上デバッグするなどして、仕様どおりに動かない原因となっている個所をプログラマ自身が究明していかなければなりません。

「〜を型に解決できません」が出てしまったら

分類:コンパイルエラー

 このメッセージは、Javaのプログラムをコーディングしていて、頻繁に見かけるエラーメッセージです。例えば、次のようなコードを見てください。

package kx;
public class Tips1_1 {
    public static void main(String[] args) {
        Strng name = "ナレッジエックス";
    }
} 

 このプログラムをコンパイル(Eclipseのデフォルトでは、ファイルを保存するとコンパイルが行われます)すると、「問題」ビューに「Strngを型に解決できません。」*1というメッセージが出ます。

 「型に解決する」という日本語がかなり難解ですが、お分かりのようにこの場合は「String」という型名が誤って「Strng」になっているためにこのようなコンパイルエラーとなります。「型に解決できません」というメッセージは、多くの場合型名の誤りが原因であると考えましょう。

*1:J2SE 5.0のjavacでコンパイルした場合は、「シンボルを見つけられません。シンボル: クラス Strng」と表示されます。

 もう1つの例をお見せします。次のコードを見てください。

package kx;
public class Tips1_2 {
    public static void main(String[] args) {
        Date d = new Date();
        System.out.println("現在時刻は:"+d);
    }
} 

 このプログラムでも、コンパイルすると「問題」ビューに「Dateを型に解決できません。」(J2SE 5.0のjavacの場合も先ほどと同様に表示)というメッセージが出ます。

 「Date」という型はJavaの標準APIに存在していますので、型名そのものの誤りではありません。ですが、Date型はjava.utilパッケージ(もしくはjava.sqlパッケージ)に属するクラスなので、パッケージ名に関する何らかの指定が必要です。

 この例では、「import java.util.Date;」を入れるか、型名を直接「java.util.Date」とすることでエラーを解消することができます。

「〜を型に解決できません」=「型名のスペルミス、パッケージ指定の欠落が主原因」


「構文エラーがあります。"}" を挿入してClassBodyを完了してください。」が出てしまったら

分類:コンパイルエラー

 このエラーも、プログラミングをしているとよく遭遇するコンパイルエラーです。例えば、次のコードを見てください。

package kx;
public class Tips1_3 {
    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            System.out.print(i);
            if (i<9) {
                System.out.print(",");
        }
    }
} 

 このプログラムをコンパイルすると、「構文エラーがあります。"}" を挿入して ClassBodyを完了してください。」というコンパイルエラーになります*2

*2:J2SE 5.0では、「'}' がありません。」と表示されます。  

 このプログラムでは何が間違っているのでしょうか? 「ClassBody」という聞き慣れない用語が出てきますが、「"}"を挿入して」と指示されていることから、“}”が足りないのであろうということは容易に想像できます。この例では、if構文の“}”に対応する“}”が不足しているために、このコンパイルエラーが出ます。ではなぜ、「ClassBody」なのでしょうか? それは、このリストのインデントを変えてみると分かります。

package kx;
public class Tips1_3 {
    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            System.out.print(i);
            if (i<9) {
                System.out.print(",");
            }
        }
    } 

 こうしてみると、if構文、for構文、メソッド定義に対する大括弧「{...}」の対応はできていますが、クラス定義部に対する大括弧の対応がないことが分かります。「ClassBody」というのは、おそらく「クラス定義部」のことをいっていると解釈できます。

 同じようなコンパイルエラーとして、「構文エラーがあります。") Statement" を挿入して IfStatement を完了してください。」というものがあります*3。次のリストを見てください。

package kx;
public class Tips1_4 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 30;
        if ((a==b)&&(b>(c-10)) {
            System.out.println("if文の成立");
        }
    }
} 
*3:J2SE 5.0では、「')' がありません。」と表示されます。

 この場合は、if構文の条件式である「((a==b)&&(b>(c-10))」に、閉じ括弧“)”が不足していることが原因でコンパイルエラーとなっています。

「〜を挿入して・・・を完了してください。」=「括弧の閉じ忘れを確認」



Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。