[???] /
[Java FAQ] / [S172]
S172: コンパイルエラー
[S172 Q-01]
エラー: Test.java を読み込めません。
error: cannot read: Test.java
[S172 A-01]
Test.java というファイル名のファイルが javac から見えない時に起こります。
ファイル名を確認してください。
ソースコードを Windows のメモ帳(Notepad.exe)で書いて保存した場合、
ファイル名が Test.java.txt となるために上記エラーになることがあります。
メモ帳で保存する場合は、"Test.java" のようにファイル名を「"」で囲んで
指定すると Test.java というファイル名で保存されます。
ファイル名の大文字、小文字の違いまで含め、Test.java という名前のファイル
があるかの確認をしてください。
参考記事 [JavaHouse-Brewers:8110] [JavaHouse-Brewers:6122]
[S172 Q-02]
test.java:1: クラス Test は public であり、ファイル Test.java で宣言しなければなりません。
test.java:1: Public class Test must be defined in a file called "Test.java"
[S172 A-02]
Test という public クラスのソースコードファイル名は Test.java です。
例外的に Windows の MS-DOSプロンプトでは、ソースコードが
public class Test {}
となっているときに
C:\> javac test.java
でコンパイルすると、test.javaというソースコードファイルでTestという
クラスが宣言されているとみなされてしまいます。
C:\> javac Test.java
とすればエラーにならずにコンパイルできます。
これはファイル名の大文字小文字を区別しない Windows 95/98/NTの
MS-DOSプロンプト(およびその上の cygwin bash など)に特有の現象です。
参考記事 [JavaHouse:4785] [JavaHouse-Brewers:2600]
[S172 Q-03]
注: Test.java は推奨されない API を使用またはオーバーライドしています。
注: 詳細については、-deprecation オプションを指定して再コンパイルしてください。
Note: Test.java uses a deprecated API.
Recompile with "-deprecation" for details.
[S172 A-03]
これは警告です。エラーではありません。
推奨されない API というのは、バージョンアップに伴い、使うことを推奨されなく
なった API です。-deprecation コンパイル時オプションをつけることにより、
どのメソッドが 推奨されない API なのかを教えてくれます。
特別な理由がない限り、新しい API に従って書くべきです。
参考記事 [JavaHouse-Brewers:16753] [JavaHouse-Brewers:16461]
[JavaHouse-Brewers:11533] [JavaHouse-Brewers:8367]
[S172 Q-04]
Date の参照はあいまいです。
java.sql の クラス java.sql.Date と java.util の クラス java.util.Date が両方適合します。
[S172 A-04]
import文中で複数の異なるDateクラスを参照可能であることが原因です。
次のようなプログラムを書いたとします。
import java.util.*;
import java.sql.*;
public class Test {
Date date;
.......
}
import文からjava.util.Dateとjava.sql.Dateが見つかりますが、
変数dateの型としてどちらを適用すればよいかコンパイラには判断できません。
次のようにソースコード中で、Dateをjava.util.Dateやjava.sql.Dateの様に
FQCN(fully-qualified class name)で書くとよいでしょう。
import java.util.*;
import java.sql.*;
public class Test {
java.sql.Date date;
.......
}
JDK標準のクラスでは、他に、java.awt.List、java.util.Listについても
同様の問題が生じる可能性があります。
関連記事[JavaHouse-Brewers:22023]
[S172 Q-05]
Test.java:4: 例外 java.net.MalformedURLException は報告されません。
スローするにはキャッチまたは、スロー宣言をしなければなりません。
Test.java:4: Exception java.net.MalformedURLException must be caught,
or it must be declared in the throws clause of this method.
[S172 A-05]
java.net.MalformedURLException に対する例外処理を記述して下さい。
メソッドやコンストラクタが例外を投げる場合は、呼び出し側は次のどちらかの対応をしなければいけません。
(1) try ... catch 構文の catch ブロックで、適切な処理をする。
try {
java.net.URL url = new java.net.URL(urlpath);
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
}
(2) throws XXXException のように例外を投げる可能性があることを宣言する。
java.net.URL getURL() throws java.net.MalformedURLException {
return new java.net.URL(urlpath);
}
関連記事[JavaHouse-Brewers:2939]
[S172 Q-06]
Test.java:2: return 文が指定されていません。
Test.java:2: Return required at end of int getNumber().
[S172 A-06]
あらゆるケースで必ず return 文を実行するようにプログラムを修正しましょう。
try ... catch 構文において、try ブロックでは return しているけれども、
catch ブロックでは return していない、あるいは、if ... else 構文において
else ブロックで return していないというのが原因ではないでしょうか。
次の場合はエラーが発生します。
public class Test {
int getNumber() {
try {
return 1;
} catch (Exception e) {
}
}
}
参考記事 [JavaHouse-Brewers:8447]
[S172 Q-07]
Test.java:13: この文に制御が移ることはありません。
dis.close();
Test.java:13: Statement not reached.
dis.close();
[S172 A-07]
全ての可能性を考慮しても実行されない文があります。
例えば、以下のようなコードの場合、return nullが実行されることはありません。
while(true)のブロックの後ろのコードなどには、「絶対に実行されない」場合があり、
意味の無い行になってしまっていることをコンパイラが教えてくれるわけです。
public class Test {
public String test() {
while (true);
return null;
}
}
関連記事[JavaHouse-Brewers:4221]
[S172 Q-08]
Test.java:8: ラベル breakpoint は未定義です。
Test.java:8: No label definition found for BreakPoint.
[S172 A-08]
次のようにするとエラーになります。
public class Test {
public static void main(String[] args) {
int count = 0;
while (true) {
while (true) {
count++;
if (count == 10) {
break breakpoint;
}
}
}
breakpoint: System.out.println(count);
}
}
breakpoint の位置を次のように変更してください。
public class Test {
public static void main(String[] args) {
int count = 0;
breakpoint: while (true) {
while (true) {
count++;
if (count == 10) {
break breakpoint;
}
}
}
System.out.println(count);
}
}
関連記事[JavaHouse-Brewers:16180]
[S172 Q-09]
Test.java:1: Test は abstract として宣言する必要があります。
Test.java:1: class Test must be declared abstract.
[S172 A-09]
abstarctクラスを継承して、非abstractクラスをつくる場合には、
継承元である abstarctクラスの abstarctメソッドをすべて実装しなければいけません。
参考記事 [JavaHouse-Brewers:2593]
[S172 Q-10]
式の開始が不正です。
[S172 A-10]
文字列の初期化など文法に従って記述されていないところがあります。
中括弧とカンマで配列の要素を代入する書き方は、宣言と同時に初期化する構文としてのみ
使用できます。
以下がこのコンパイルエラーの出る例です。
class Test {
String[] foo;
Test() {
foo = {"java", "javac"};
}
}
以下のような書き方にするとエラーを回避できます。
class Test {
String[] foo;
Test() {
foo = new String[]{"java", "javac"};
}
}
なお、JDK1.2.2までは「配列定数は初期化子でのみ使用できます。」と、
より理解しやすいメッセージでした。
[S172 Q-11]
static でない メソッド bar() を static コンテキストから参照することはできません。
[S172 A-11]
クラスメソッドのなかでは、明示的なインスタンス指定をせずに
インスタンスメソッドを呼び出すことはできません。
以下がコンパイルエラーになる例です。
class Test {
void bar() {
}
static void staticMethod() {
bar();
}
}
以下のようにインスタンスを生成し、そのインスタンスに対して bar() を呼ぶように書きなおすとよいでしょう。
class Test {
void bar() {
}
static void staticMethod() {
Test test = new Test();
test.bar();
}
}
なお、JDK1.2.2 以前ですと以下のメッセージになります。
class Test のメソッド void bar() に static 参照することはできません。
S011-05も参照してください。
[S172 Q-12]
XXXException はすでにキャッチされています。
[S172 A-12]
Exception をキャッチする順番を誤って記述している可能性があります。
例えば以下の場合に上記エラーがでます。
class Test {
void foo() {
try {
java.net.URL url = new java.net.URL("..");
java.io.InputStream is = url.openStream();
} catch (java.io.IOException e) {
e.printStackTrace();
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
}
}
}
MalformedURLException は IOException のサブクラスですので、
catch (java.io.IOException e) でキャッチされてしまいます。
catch (java.net.MalformedURLException e) でキャッチしてURL を再入力させたいという
プログラマの意図通り動かないわけで、バグのもとになるためにコンパイルエラーになります。
以下のようにキャッチの順番を入れ替えると、意図どおりになり、
コンパイルエラーにもならないでしょう。
class Test {
void foo() {
try {
java.net.URL url = new java.net.URL("..");
java.io.InputStream is = url.openStream();
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
JDK1.2.2 までは「この catch 節に制御が移ることはありません。」の
エラーメッセージになります。
[S172 Q-13]
シンボルを解釈処理できません。
[S172 A-13]
一般にコンパイラから見えないシンボルがあるのが原因です。
次のプログラムを考えてみましょう。
class Test {
InputStreamReader isr;
}
これはコンパイルエラー
シンボルを解釈処理できません。
シンボル: クラス InputStreamReader
が発生します。クラス InputStreamReader が見つからないのです。
class Test {
java.io.InputStreamReader isr;
}
とすればコンパイルできるようになります。
次に以下のソースコードをコンパイルしてみましょう。
class Test extends java.io.InputStreamReader {
Test() {
}
}
これも、
Test.java:2: シンボルを解釈処理できません。
シンボル: コンストラクタ InputStreamReader ()
位置 : java.io.InputStreamReader の クラス
Test() {
^
エラー 1 個
というエラーメッセージがでます。
コンストラクタ Test() の一行目でスーパークラスのコンストラクタを
明示的に書いていない場合には、スーパークラスの引数なしのコンストラクタを
呼ぶようにコンパイルされます。
Test のスーパークラスである InputStreamReader には引数なしのコンストラクタが
ありませんからコンパイルエラーになります。
S010-03も参照してください。
[S172 Q-14]
スーパータイプのコンストラクタの呼び出し前は...を参照できません。
[S172 A-14]
コンストラクタ内で、スーパークラスのコンストラクタの呼び出しが終わった後でないと、
自分のインスタンス変数へのアクセス、インスタンスメソッドの呼び出しはできません。
次のプログラムではこのエラーが発生します。
class Test extends java.io.InputStreamReader {
java.io.InputStream is;
Test() {
super(is);
}
例えば次のようにコンストラクタの引数に必要なインスタンスを与えると回避できます。
class Test extends java.io.InputStreamReader {
Test(java.io.InputStream givenInputStream) {
super(givenInputStream);
}
}
[S172 Q-15]
変数...は初期化されていない可能性があります。
[S172 A-15]
ローカル変数は、使用される以前に必ず初期化されていなければなりません。
実行時の条件分岐や例外発生によって初期化されない場合があるとコンパイルエラーになります。
S012-02 を参照してください。
[S172 Q-16]
packageを指定したらコンパイルできなくなったのですが?
[S172 A-16]
指定されたクラス群が、各コマンド(java、javac 等)が参照できる場所に
無いことが原因です.
S017-06 を参照してください。
[S172 Q-17]
ClassA の methodA() は InterfaceA の methodA() を実装できません:
弱いアクセス特権に割り当てようとしたのは public でした。
[S172 A-17]
public で宣言しなければならない methodA() に対して、
アクセス修飾子なし、または、protected, private で宣言しています。
インタフェースはアクセス修飾子がない場合、 public と宣言されているのと同等です。
次のプログラムはエラーになります。
interface InterfaceA {
void methodA();
}
class ClassA {
protected void methodA(){}
}
class SubClassA extends ClassA implements InterfaceA {
}
これは
interface InterfaceA {
void methodA();
}
class ClassA {
public void methodA(){}
}
class SubClassA extends ClassA implements InterfaceA {
}
のようにするか、
interface InterfaceA {
void methodA();
}
class ClassA {
protected void methodA(){}
}
class SubClassA extends ClassA implements InterfaceA {
public void methodA() {}
}
にすればエラーを回避できます。
[S172 Q-18]
Test.java:4: 変数 intValue は初期化されていない可能性があります。
Test.java:4: Variable intValue may not have been initialized.
[S172 A-18]
ローカル変数 intValue を初期化してください。
Javaでは、ローカル変数は暗黙の初期化はされません。
public class Test {
public int someMethod() {
int intValue;
return intValue;
}
}
のようなソースコードで上記エラーメッセージがでます。この場合は、
int intValue = 0 // 0 is default value
と、文脈にしたがって初期化値を与えてください。
参考記事 [JavaHouse-Brewers:3622]
[S172 Q-19]
abstract final void someMethod(); がコンパイルエラーにならないのですが?
[S172 A-19]
Java 2 SDK 1.2 より前の javac のバグです。
Java 2 SDK 1.2 以降では、以下のようなエラーになります。
Test.java:2: 修飾子 abstract と final の組み合わせは不正です。
abstract final void someMethod();
Test.java:2: Abstract methods can't be final: void someMethod()
abstract final void someMethod();
参考記事 [JavaHouse-Brewers:1359]
[S172 Q-20]
JDK 1.1.? の javac で、日本語エラーメッセージにできませんか?
[S172 A-20]
JDK 1.1.1 Japanese Supplement をインストールすればよいです。
Solaris と Windows 用が以下の URL にあります。
バージョン依存性、ロケール依存性がありますので、注意してください。
http://java.sun.com/products/jdk/1.1/ja/index.ja.html
参考記事 [JavaHouse-Brewers:9652] [JavaHouse-Brewers:9355]
[S172 Q-21]
JDK 1.0.2 の javac で、日本語エラーメッセージにできませんか?
[S172 A-21]
個人利用の範囲ならば、以下の URL に日本語訳した javac.properties があります。
著作権がクリアーでないので、再配布は禁止です。
JDK-Install-Directory/lib/javac.properties と入れ換えてご利用ください。
http://java-house.etl.go.jp/ml/archive/j-h-b/001388.html#body
参考記事 [JavaHouse-Brewers:1388] [JavaHouse-Brewers:1324]
[S172 Q-22]
error message '......' not found
[S172 A-22]
javac が参照するエラーメッセージファイルがないためです。
よくわからなければ、JDK を再インストールしたほうがよいでしょう。
以下で、追試してみます。
JDK 1.0.2 では、JDK-Install-Directory/lib/javac.properties が
エラーメッセージファイルです。これを javac.properties.disable に
ファイル名を変えます。そして、例えば存在しないファイル名 Not.java
を指定してコンパイルしてみます。
$ javac Not.java
failed to read: C:\JDK1.0.2\BIN\..\lib\javac.properties
error: error message 'cant.read' not found
1 error
また、javac.properties ファイルは、それぞれ
JDK 1.1 では JDK-Install-Directory/lib/classes.zip のなか、
Java 2 SDK 1.2、1.3 では JDK-Install-Directory/lib/tools.jar のなか
に固められてありますので、JDK1.1 以降で、このエラーメッセージを
みることは、めったにないでしょう。
Java 2 SDK 1.2、1.3 の場合は tools.jar のなかには、
javac.properties、javac_ja.properties があるので、
Windows なら「地域」の変更(場合によってはリブートが必要)、
UNIX なら環境変数 LANG の変更だけで、
エラーメッセージを英語と日本語とに切り換えることができます。
参考記事 [JavaHouse-Brewers:8636]
[S172 Q-23]
java.io.UTFDataFormatException
at java.io.DataInputStream.readUTF(DataInputStream.java:326)
[S172 A-23]
DataInputStream#readUTF() のバグのために起こるエラーです。
Mac、Windows、SolarisSPARC2.5.1 の JDK1.0.2 で起こります。
それ以外の環境では起こらないという意味ではなく、未確認です。
以下で再試してみます。
// Root.java
class Root {
static String s = "\u52d5\u8a5e"; // 動詞
}
// Main.java
class Main extends Root {
public static void main(String[] args) {
System.out.println(s);
}
}
という二つのファイルを用意し、Root.java、Main.java の順でコンパイルします。
$ javac Root.java
$ javac Main.java
java.io.UTFDataFormatException
at java.io.DataInputStream.readUTF(DataInputStream.java:326)
at java.io.DataInputStream.readUTF(DataInputStream.java:281)
at sun.tools.java.BinaryConstantPool.(BinaryConstantPool.java:47)
at sun.tools.java.BinaryClass.load(BinaryClass.java:67)
at sun.tools.javac.BatchEnvironment.loadFile(BatchEnvironment.java:190)
at sun.tools.javac.BatchEnvironment.loadDefinition(BatchEnvironment.java:319)
at sun.tools.java.Environment.loadDefinition(Environment.java:110)
at sun.tools.java.ClassDeclaration.getClassDefinition(ClassDeclaration.java:110)
at sun.tools.javac.SourceClass.basicCheck(SourceClass.java:460)
at sun.tools.java.ClassDeclaration.getClassDefinition(ClassDeclaration.java:116)
at sun.tools.javac.Main.compile(Main.java:192)
at sun.tools.javac.Main.main(Main.java:289)
Main.java:1: Superclass Root of class Main not found.
class Main extends Root {
^
1 error
となります。Root.java と Main.java を一つのファイルにまとめて、
コンパイルすると上記エラーはでません。
contributor: N.Amemiya, Norikazu Nakato
コメントの送り先 Java FAQ BBS