連載
» 2006年06月07日 00時00分 公開

デバッグのヒント教えます(3):「到達不可能なCatchブロック」が出てしまった

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

 6月といえば、関東ではそろそろ梅雨の季節ですね。私は北海道出身なので、実は就職で東京に移るまでは梅雨を経験したことがありませんでした。北海道の6月は非常に過ごしやすい時期なので、最初はこの季節に違和感があったものですが、いまではだいぶ梅雨の季節感に慣れてきました。じめじめした季節はデバッグも何となく憂うつになってしまいそうですが、今回のTipsを読んで皆さんが少しでもデバッグを早く終わらせることができたら、と思います。今月もどうぞお付き合いください。

「到達不可能なcatchブロック」が出てしまった

分類:コンパイルエラー

 コンパイルエラーは、メッセージとともにエラーの発生した行番号が出ますので、その行だけに注目していれば対応できるはずなのですが、そうでない場合もあります。

 次の例を見てください。

package kx;
import java.sql.SQLException;
public class Tips2_1 {
    public static void main(String[] args) {
        try {
            System.out.println("Hello World!");
        } catch(SQLException ex) {
            System.out.println("SQLExceptionが発生");
        }
    }
} 

 このプログラムをコンパイルすると、「SQLException の到達不可能な catch ブロック。 この例外は、try ステートメント本体からはスローされません。」というメッセージが表示されます。

「SQLException の到達不可能な catch ブロック。  この例外は、try ステートメント本体からはスローされません。」というメッセージが表示される 「SQLException の到達不可能な catch ブロック。 この例外は、try ステートメント本体からはスローされません。」というメッセージが表示される
注:J2SE 5.0のjavacでコンパイルした場合は、「例外 java.sql.SQLException は対応する try文の本体ではスローされません。」と表示されます。

 「到達不可能なcatchブロック」という言葉は、そのcatch節が絶対に実行されることがない、すなわち、catch節に対応するtry節の中で、catch節に書かれた例外が発生しないことを意味しています。ですから、このコンパイルエラーが出たときには、

  1. このcatch節の記述を削除し、全くcatch節を必要としないのであればtry節ごと削除してしまう
  2. このcatch節に記述された例外の型名を、適切なものに置き換える

のどちらかを行えばよいということになります。これとは逆に、例外が発生する可能性があるにもかかわらずtry〜catch節を記述していない場合は、「「処理されない例外の型 Exception」が出てしまったら」で紹介したコンパイルエラーが発生します。

 ちなみに、プログラムを書いているときに、ある処理で例外が起きる可能性があるかどうかはどのように判断すればよいのでしょうか。標準APIや、他者の作成したライブラリを利用している場合は、呼び出そうとしているクラスのJavadocを見ることによってそのメソッドがどんな例外を発生させる可能性があるか知ることができます。Javaでは、メソッド定義部に、発生する可能性のある例外を定義することになっているため、ソースの内容をすべて読まなくても、メソッド定義部だけを見ればよいのです。

「到達不可能なcatchブロック」=必要のない例外に対してcatch節を書いていないかチェック


前後を見ないと分からないコンパイルエラー

分類:コンパイルエラー

 このコンパイルエラーは、例外処理を扱うプログラミングをしている場合によく遭遇するものです。次の例を見てください。

package kx;
public class Tips2_2 {
    public static void main(String[] args) {
      int a=100;
        int b=200;
        int c=0;
        if ((a*b)>10000) {
        System.out.println
            System.out.println("a*b="+(a*b));
    }
    }
}

 このプログラムをコンパイルすると、「トークン "." に構文エラーがあります。正しくは ; です。」とコンパイルエラーが表示され、その行番号には「行15」と表示されます。

「トークン 「トークン "." に構文エラーがあります。正しくは ; です。」とコンパイルエラーが表示される
注:J2SE 5.0のjavacでコンパイルした場合は、「';' がありません。」と表示されます。

 しかし、15行目を見ても、特に間違っているところはなさそうです。ではいったいどうしてこの行がエラーになってしまうのでしょうか。このような場合は、エラーとなっているその行だけではなく、その行の前後の行も確認してみてください。このプログラムでは、実は前の行の末尾にメソッドの引数指定「()」や文の末尾を示す「;」が抜けているのがこのコンパイルエラーの原因なのですが、「;」がないことによってこの行と次の行が同一の行と見なされてしまうために、このようなコンパイルエラーになってしまうのです。

 これと似たようなケースとして、括弧や中括弧の対応が不完全な場合に、ほかの行がコンパイルエラーになってしまうこともあります。コンパイルエラーが起こった場合、まずはエラーが起きた行に注目して原因を調べていきますが、前後の行の記述にも注意してみると原因の発見を早めることができます。

コンパイルエラーになった行には構文の誤りが見当たらない=前後の行に誤りがないかどうか調べる。特に「;」の付け忘れ、「(…)」「{…}」の対応に注意


変数やインスタンスが「static参照できません」といわれる

分類:コンパイルエラー

 このエラーメッセージは一見するとstatic定義されたメソッドやフィールドにアクセスするコードに対して表示されるように思えますが、実際にはその逆です。次の例を見てください。

package kx;
public class Tips2_3 {
    double pi = 3.14;
  public int cube(int a) {
      return a*a*a;
    }
    public static void main(String[] args) {
        System.out.println("円周率は"+pi);
        System.out.println("16の3乗は"+cube(16));
    }
} 

 このプログラムをコンパイルすると、

 「非 static フィールド pi を static 参照できません。」

 「型 Tips2_3 から非 static メソッド cube(int) に static 参照することはできません。」

というコンパイルエラーが表示されます。

「非 static フィールド  pi を static 参照できません。」 「型 Tips2_3 から非  static メソッド cube(int) に  static 参照することはできません。」というコンパイルエラーが表示される 「非 static フィールド pi を static 参照できません。」 「型 Tips2_3 から非 static メソッド cube(int) に static 参照することはできません。」というコンパイルエラーが表示される
注:J2SE 5.0のjavacでコンパイルした場合は、「static でない 変数 pi を static コンテキストから参照することはできません。」「static でない メソッド cube(int) を static コンテキストから参照することはできません。」と表示されます。

 メソッドをstatic定義すると、そのクラスのインスタンスの有無にかかわらずメソッドを実行することができるため、使い方によっては非常に便利です。しかし、文法上の制約として、static定義されたメソッドから、static定義されていないフィールドやメソッドにアクセスすることはできないことになっています。この例では、mainメソッド(このメソッドはクラスの起動に使われる特別なメソッドで、static定義されることになっています)から、piというフィールド(static定義されていない)や、cubeというメソッド(static定義されていない)を参照したり、実行したりしようとしたために、このようなコンパイルエラーが表示されます。

 この例では、自分自身のインスタンスをいったん生成してから、そのインスタンスを経由してフィールドやメソッドにアクセスすることで、問題を解決することができます。

package kx;
public class Tips2_3 {
    double pi = 3.14;
    public int cube(int a) {
        return a*a*a;
    }
    public static void main(String[] args) {
        Tips2_3 tips = new Tips2_3();
        System.out.println("円周率は"+tips.pi);
        System.out.println("16の3乗は"+tips.cube(16));
    }
}

「static参照できません」=static定義されたメソッドからstatic定義されていないフィールドやメソッドにアクセスしていないかチェック



Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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