Rits Logo 立命館大学 情報理工学部 情報コミュニケーション学科
MobileComputing Lab.
Last Update : Nov. 13, 2006

[section]Javaエラーメッセージの傾向と対策

Javaのプログラムを書いているとコンパイル時や実行時に様々なエラーに遭遇します.ここではよくみかけるエラーについて,傾向と対策をQ&A形式で説明していきます.

Table of Contents

コンパイル時エラーの傾向

その1

以下に示すプログラムをHello.javaという名前で作成してコンパイルしたところ,その下に示すようなエラーメッセージが表示されました.なぜでしょうか?

対策はここ

public class Hallo {
  public static void main(String[] args) {
    System.out.println("Hello World") ;
  }
}
		
C:\>javac Hello.java
Hello.java:1: クラス Hallo は public であり、ファイル Hallo.java で宣言しなければなりません。
public class Hallo {
       ^
エラー 1 個
		

その2

Javaの参考書に載ってるプログラムをそのまま入力してコンパイルしたらエラーがでました.最初からつまずいて凹んでます.

対策はここ

public class Hello {
  public static void main(String[] args) {
    System.out.printIn("Hello World") ;
  }
}
		
C:\>javac Hello.java
Hello.java:3: シンボルを解決できません。
シンボル: メソッド printIn (java.lang.String)
場所    : java.io.PrintStream の クラス
    System.out.printIn("Hello World") ;
              ^
エラー 1 個
		

その3

今度はエラーが3つも出てきました.一見するとプログラムはおかしくないようなのですが,Javaに嫌われてるのでしょうか?

対策はここ

public class Hello {
  public static void main(String[] args) {
    System.out.println("Hello World") ;
  }
}
		
C:\>javac Hello.java
Hello.java:4: \65373 は不正な文字です。
  }
  ^
Hello.java:5: ';' がありません。
}
^
Hello.java:6: '}' がありません。
^
エラー 3 個
		

その4

よくわからないエラーが出ました.どこが悪いのでしょうか?

対策はここ

public class Hello {
  pablic static void main(String[] args) {
    System.out.println("Hello World") ;
  }
}
		
C:\>javac Hello.java
Hello.java:2: <identifier> がありません。
  pablic static void main(String[] args) {
         ^
Hello.java:5: ';' がありません。
}
^
エラー 2 個
		

その5

プログラムは正しいと思うのに,次のようなエラーがでました.コンパイラがおかしいんじゃないでしょうか?

対策はここ

public class Calc {
  public static void main(String[] args) {
    System.out.println("Calc Result : " + calc(10, 2)) ;
  }
  public static int calc(int a, int b) {
    if (b >= 0) {
      return (a * b) ;
    } else if (b < 0) {
      return (a * (-b)) ;
    }
  }
}
		
C:\>javac Calc.java
Hello.java:11: return 文が指定されていません。
  }
  ^
エラー 1 個
		

その6

セミコロン(;)がないって言われるのですが,ちゃんと行末についてます.Javaが壊れちゃったんでしょうか?

対策はここ

public class Calc {
  public static void main(String[] args) {
    int a = calc(10, 2)
    System.out.println("Calc Result : " + a) ;
  }
  public static int calc(int a, int b) {
    if (b >= 0) {
      return (a * b) ;
    } else {
      return (a * (-b)) ;
    }
  }
}
		
C:\>javac Calc.java
Calc.java:4: ';' がありません。
    System.out.println("Calc Result : " + a) ;
    ^
エラー 1 個
		

その7

classinterfaceがないって言われます.ちゃんとクラスの定義をしているつもりなのですが...

対策はここ

public class Sample {
  public static void main(String[] args) {
    int a = calc(10, 2) ;
    print(a) ;
  }
  public static int calc(int a, int b) {
    int c ;
    if (b >= 0) {
      c = a * b ;
      return (c) ;
    } else
      c = a * (-b) ;
      return (c) ;
    }
  }
  public static void print(int a) {
    System.out.println("Result : " + a) ;
  }
}
		
C:\>javac Sample.java
Sample.java:16: 'class' または 'interface' がありません。
  public static void print(int a) {
                ^
Sample.java:19: 'class' または 'interface' がありません。
}
^
Sample.java:20: 'class' または 'interface' がありません。
^
エラー 3 個
		

実行時エラーの傾向

その1

コンパイルは正しく通ったのに実行時にエラーが発生します.なぜでしょうか.

対策はここ

public class Hello {
  public void main(String[] args) {
    System.out.println("Hello World") ;
  }
}
		
C:\>java Hello
Exception in thread "main" java.lang.NoSuchMethodError: main
		

その2

プログラムを実行したら途中まで実行できたのにエラーがでました.どういうことでしょうか?

対策はここ

public class Array {
  public static void main(String[] args) {
    int[] array = new int[5] ;
    for (int i = 0 ; i <= array.length ; i++) {
      array[i] = i * i ;
      System.out.println("array[" + i + "] = " + array[i]) ;
    }
  }
}
		
C:\>java Array
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
        at Array.main(Array.java:5)
		

その3

第10回宿題のプログラムをいじっていたら変なエラーが発生しました.「NullPointerException」って何なんですか?

注:ここではエラーが発生する最小限の状態のプログラムを示しています.

対策はここ

public class Link {
  public int  data ;
  public Link next ;
  public Link(int d) {
    data = d ;
    next = null ;
  }
}
		
public class LinkList {
  private Link first ;
  public LinkList() {
    first = null ;
  }
  public Link deleteFirst() {
    Link target = first ;
    first = first.next ;
    return (target) ;
  }
}
		
public class LinkListTest {
  public static void main(String[] args) {
    LinkList list = new LinkList() ;
    list.deleteFirst() ;
  }
}
		
C:\>java LinkListTest
Exception in thread "main" java.lang.NullPointerException
        at LinkList.deleteFirst(LinkList.java:8)
        at LinkListTest.main(LinkListTest.java:4)
		

その4

これまで普通に使えていたのに急にJavaの環境がおかしくなりました.コンパイルはできるのに実行ができません.

対策はここ

C:\>java Test
Exception in thread "main" java.lang.NoClassDefFoundError: Test
		

コンパイル時のエラーの対策

その1

Javaのソースファイルを作成するときには,そのファイル中で定義したpublicなクラスとファイル名は一致させておく必要があります.この場合,ファイル名がHello.javaとなっているのに,ソースファイルの中のクラス名が(おそらくタイプミスで)Halloとなっているため,エラーが発生しています.エラーメッセージには,エラーが発生したファイルの名前と行番号が最初に「Hello.java:1: 」と出ているので,注意深くメッセージを読めばすぐに気づくでしょう.

その2

原因は小文字のエル(l)と大文字のアイ(I)を間違って入力してしまうという非常に単純なミスです.本に載っているプログラムは,文字の区別がつきにくいことがよくあるので,気にしなくてもいいでしょう.

せっかくですのでここではもう少し詳しくエラーメッセージについてみていきましょう.まずはメッセージの1行目に注目してください.「Hello.java:3: シンボルを解決できません。」というメッセージが出ています.この「シンボルが解決できません」というメッセージはこれからもちょくちょく出てきますので,意味を覚えておくといいでしょう.このメッセージの意味は,コンパイル中に「知らない言葉がでてきたよ」という意味だと思ってもらえばいいです.最初に「Hello.java:3: 」と出ているので,「Hello.javaというファイルの3行目に,知らない言葉が出てきたよ」ということになります.

2行目には具体的に意味のわからなかった言葉(シンボル)が示されています.「メソッド printIn (java.lang.String)」と書かれていますので,「メソッドでprintInなんて名前のものは知らない」ということです.

3〜4行目には,該当行のどの部分にエラーがあるかが,「^」という記号で示されています.これを手がかりにどこにミスがあるのかを見つけ出せばいいわけです.

その3

Javaは(あたりまえですが)嫌いだからエラーをだすなんてことはありません.ちゃんと(!?)間違っています.

Hello.java:4: \65373 は不正な文字です。」と書かれているように,ちょっとわかりにくいかもしれませんが,4行目に間違いがあります.間違いは,その下に書かれているように「」の部分です.一見正しいようですが,半角の「}」であるべきところが,全角の「」になってしまっています.「\65373」はJavaが使う文字コード(Unicode)において「」を示しています.

この他にも,間違って全角の空白「 」を書いてしまった場合にも同じようなエラーが発生します.エディタとして秀丸を使っているならば,「ファイルタイプ別の設定」の中で「全角空白」を表示する機能をONにしておくといいでしょう.

残りのエラーは,この部分がおかしくなっているために連鎖的に発生していますので,半角の「}」に直してしまえばエラーは消えてしまいます.例えば,最後のエラー「Hello.java:6: '}' がありません。」は,文字の全角と半角を間違ったために閉じ括弧「}」が足りなくなったために発生しているのです.

このように,Javaのコンパイラは,コンパイル時にまとめていくつかのエラーを表示します.1つの間違いから複数のエラーが発生することがありますので,たくさんエラーが出たときは,すべてのエラーを一度に修正するのではなく,一つずつ順番に修正していくといいでしょう.

その4

間違いの原因は「public」の綴りを「pablic」と間違えたことです.綴り間違いがあったため,Javaのコンパイラが「pablic」の次に来るだろうものを誤解してエラーが発生しています.2つめの「;」がない,というエラーも,最初の綴り間違いが引き金ですので,綴りを直せばエラーは消えます.

その5

5行目から始まるcalcメソッドを見てください.このメソッドはint型の値を返すという定義になっています.ということで,このメソッドはどこかで必ずreturn文によって値を返す必要があります.ところが,そのreturn文が見つからないため,メソッドの最後の行である11行目に対して,「Hello.java:11: return 文が指定されていません。」というエラーが表示されているのです.

このプログラムでは,if文の中で「変数b0以上」であれば「a*b」の計算結果を,else if文の中で「変数b0未満」であれば,「a*(-b)」の計算結果を返すようにreturn文が書かれています.

人がプログラムを読めば,必ずどちらかの結果が返るということはすぐにわかります.しかし,Javaのコンパイラはそこまで賢くないので変数bの値を考慮しません.つまり,if文やelse if文があった場合,条件が成立する場合と成立しない場合のすべてのパターンを考えて,それぞれのプログラムの流れの中でreturn文が出現しているかどうかだけをチェックしているのです.このメソッドでは,if文とelse if文のどちらも条件が成立しなかった場合の流れにおいて,return文が出現していませんので,エラーになっているのです.

このエラーをなくすには,以下の3通りにプログラムを書き換える必要があります.どれでも動作結果は同じになりますが,すっきりするのは1番目のプログラムでしょう.

// パターン1
public class Calc {
  public static void main(String[] args) {
    System.out.println("Calc Result : " + calc(10, 2)) ;
  }
  public static int calc(int a, int b) {
    if (b >= 0) {
      return (a * b) ;
    } else {                    // (b < 0) の場合
      return (a * (-b)) ;
    }
  }
}
		
// パターン2
public class Calc {
  public static void main(String[] args) {
    System.out.println("Calc Result : " + calc(10, 2)) ;
  }
  public static int calc(int a, int b) {
    if (b >= 0) {
      return (a * b) ;
    } else if (b < 0) {
      return (a * (-b)) ;
    } else {
      return (0) ;              // ここに来ることはない
    }
  }
}
		
// パターン3
public class Calc {
  public static void main(String[] args) {
    System.out.println("Calc Result : " + calc(10, 2)) ;
  }
  public static int calc(int a, int b) {
    if (b >= 0) {
      return (a * b) ;
    } else if (b < 0) {
      return (a * (-b)) ;
    }
    return (0) ;                // ここに来ることはない
  }
}
		

その6

エラーメッセージにある通り,セミコロン(;)をつけ忘れています.注意するのは,たいていの場合,セミコロンを忘れた行の次の行でエラーが表示されるという点です.この例では,「Calc.java:4: ';' がありません。」と表示されて,4行目の内容が表示されています.しかし,4行目にはちゃんとセミコロンがあるため「なんでだ〜?」と思うでしょう.このとき,エラーの場所を示す記号「^」の場所をよく見てください.4行目の先頭になっていますよね.これはつまり,この位置(=つまり前の行の最後)にセミコロンがないとおかしい,と言っているのです.

その7

16行目,19行目,20行目で「'class' または 'interface' がありません。」という同じエラーメッセージがでていますね.説明のためにプログラムに行番号をつけてみました.

 1: public class Sample {
 2:   public static void main(String[] args) {
 3:     int a = calc(10, 2) ;
 4:     print(a) ;
 5:   }
 6:   public static int calc(int a, int b) {
 7:     int c ;
 8:     if (b >= 0) {
 9:       c = a * b ;
10:       return (c) ;
11:     } else
12:       c = a * (-b) ;
13:       return (c) ;
14:     }
15:   }
16:   public static void print(int a) {
17:     System.out.println("Result : " + a) ;
18:   }
19: }
20: 
		

16行目以降にエラーが集中しているので,エラーメッセージを見ると,この16〜20行目あたりにミスがあるのかと思ってしまいます.けれども,実は間違いはもっと前の部分にあるのです.どこかというと,11行目です.そう,else文の後ろに開き中括弧({)を書き忘れているのです.

実は,Javaのif文などでは,条件が成立したときの処理の文が1行の場合,中括弧で囲まなくてもいいことになっているのです.つまり,今のプログラムでは,12行目のみがelse文の処理の中身だと考え,13行目はif-elseの処理を抜けた後の部分だと,コンパイラが考えたわけです.

この考えにしたがって,プログラムのインデントを書き直してみると次のようになります.

 1: public class Sample {
 2:   public static void main(String[] args) {
 3:     int a = calc(10, 2) ;
 4:     print(a) ;
 5:   }
 6:   public static int calc(int a, int b) {
 7:     int c ;
 8:     if (b >= 0) {
 9:       c = a * b ;
10:       return (c) ;
11:     } else
12:       c = a * (-b) ;
13:     return (c) ;
14:   }
15: }
16:   public static void print(int a) {
17:     System.out.println("Result : " + a) ;
18:   }
19: }
20: 
		

これを見れば,なぜ変なエラーがでたかはわかりますね.コンパイラとしては,15行目でSampleクラスの宣言が終わっていると考えたわけです.そうすると,16行目以降には新たなクラスの宣言がでてくると考えます.というわけで,16行目以降にに「'class' または 'interface' がありません。」というエラーが出てきたわけです.

ここで皆さんに覚えて欲しいのは,以下のことです.

エディタとして秀丸を使っているなら,「対応する括弧の強調表示」という機能がありますので,これをONにして,括弧の対応関係をきっちりと確認するといいでしょう.

また,中括弧を書かずにプログラムを書くと読みにくくなるので,たとえ処理内容が1行で書けても中括弧で囲む癖をつけてください.

実行時のエラーの対策

その1

Javaの実行時エラーは例外という形で発生します.ここでのエラーは「java.lang.NoSuchMethodError: main」というものです.エラーの意味はクラスNoSuchMethodErrorの説明を参照してください.簡単に言ってしまうと「mainメソッドが見つからない」ということです.

おかしいですね.ちゃんとmainメソッドはあります.でも,注意深くみると間違いがあることがわかります.どこかというと「static」が抜けているという点です.Javaは実行するときに,コマンドラインで指定されたクラス(ここではHello)のpublicstaticmainという名前で,引数がStringクラスの配列であるメソッドから実行を開始します.この場合,「static」が抜けているために,必要なメソッドが見つからなかったのです.

例えば,次のプログラムでも同様のエラーが発生します.このプログラムの間違いは,引数がStringクラスの配列ではなく,Stringクラスの変数になっているところです.よく見ると,配列を表す「[]」がStringの後ろに抜けていますよね.

public class AnotherHello {
  public static void main(String args) {
    System.out.println("Hello World") ;
  }
}
		

その2

ここで出ているArrayIndexOutOfBoundsExceptionも非常によくみかける実行時例外です.発生する例外クラス名からわかるように,配列(array)の添字(index)が範囲外(out of bounds)になりましたよ,ということです.

ここでは「Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5」と表示されているように,「5」という値が配列の範囲外であることを示しています.また,「at Array.main(Array.java:5)」とあるように,Array.javaというファイルの5行目で発生していることもわかります.

このプログラムの間違いは,for文の終了条件「i <= array.length」です.array.lengthは配列の長さを表していますが,配列の添字は0から始まりますので,最後の添字は配列の長さよりも1だけ小さい値になります.ということで,終了条件は正しくは「i < array.length」としておかないと,配列の後ろに踏み外してしまいます.

その3

nullとは,「参照の不在」,つまり変数がオブジェクトや配列を参照していないことを表す予約値です.NullPointerExceptionはオブジェクトや配列が必要な場合に,nullを使おうとすると発生します.詳しい説明はクラスNullPointerExceptionの説明を読んでください.

ここでは,どうやれば例外の発生場所がわかるかを説明します.エラーメッセージの3行目「at LinkListTest.main(LinkListTest.java:4)」を見てください.ここから,LinkListTest.javaの4行目でエラーが発生していることがわかります.そして,その上にある「at LinkList.deleteFirst(LinkList.java:8)」から,実際には,LinkListTest.javaの4行目で呼び出されるLinkList.javaというファイルの8行目,すなわちLinkListクラスのdeleteFirstメソッドの中で発生していることがわかります.

該当する8行目を見ると「first = first.next ;」となっており,firstnullが入っているとまずいことがわかります.リストは初期状態では何もありませんので,firstにはnullが入っていますから,このときにdeleteFirstメソッドを呼び出すとまずいわけです.

ということで,講義時間にも述べたように厳密なdeleteFirstメソッドは以下のようになります.

public Link deleteFirst() {
  if (first != null) {
    Link target = first ;
    first = first.next ;
    // size-- ;  // リストの長さを記憶している場合
    return (target) ;
  }
  return (null) ;
}
		

その4

エラーの意味は,「Test」というクラスが見つかりません,ということです.コンパイルは正しくできていますか?正しくコンパイルできて,Test.classというファイルができているのであれば,Javaの環境がおかしくなっている可能性があります.具体的には,「CLASSPATH」の設定がおかしくなっている可能性が高いです.自分で「CLASSPATH」を変更した場合は,正しく修正してください.また,そうでない場合は,おかしくなる前にソフトウエアをインストールしていないか思い出してみてください.例えば,私の環境ではAppleiTunesをインストールする際に,不具合が発生することが確認できています.他のソフトウエアでも同様の問題が起こることが考えられますので,対処方法のページを参考にしてみてください.

参考文献

このページを作成するにあたって,以下の文献を参考にしました.