487

「シンボルが見つかりません」、「シンボルを解決できません」、または「シンボルが見つかりません」というエラー (Java の場合) について、次のことを説明してください。

  • 彼らはどういう意味ですか?
  • それらを引き起こす可能性のあるものは何ですか?
  • プログラマーはそれらをどのように修正しますか?

この質問は、Java でのこれらの一般的なコンパイル エラーに関する包括的な Q&A をシードするように設計されています。

4

17 に答える 17

507

0. 2 つのエラーに違いはありますか?

あまり。「シンボルが見つかりません」、「シンボルを解決できません」、「シンボルが見つかりません」はすべて同じ意味です。Java コンパイラが異なれば、使用する表現も異なります。

1. 「シンボルが見つかりません」というエラーは何を意味しますか?

まず、コンパイルエラーです1。これは、Java ソース コードに問題があるコンパイル方法に問題があることを意味します。

Java ソース コードは、次のもので構成されます。

  • キーワード: like、、classなどwhile
  • リテラル: true、、、、など。false_42'X'"Hi mum!"
  • 演算子およびその他の英数字以外のトークン: +={など。
  • 識別子: Reader、、、、iなどtoStringprocessEquibalancedElephants
  • コメントと空白。

「シンボルが見つかりません」というエラーは、識別子に関するものです。コードがコンパイルされると、コンパイラはコード内のすべての識別子が何を意味するのかを理解する必要があります。

「シンボルが見つかりません」というエラーは、コンパイラがこれを実行できないことを意味します。あなたのコードは、コンパイラが理解できないものを参照しているようです。

2.「シンボルが見つかりません」エラーの原因は何ですか?

まず第一に、原因はただ一つ。コンパイラは、識別子を定義する必要があるすべての場所を調べましたが、定義が見つかりませんでした。これは、さまざまな原因で発生する可能性があります。一般的なものは次のとおりです。

  • 一般的な識別子の場合:

    • 名前のスペルが間違っている可能性があります。すなわちStringBiulderの代わりにStringBuilder。Java は、スペルミスやタイプミスを修正することはできませんし、修正しようともしません。
    • おそらくケースを間違えたでしょう。すなわちstringBuilderの代わりにStringBuilder。すべての Java 識別子は大文字と小文字が区別されます。
    • アンダースコアを不適切に使用した可能性があります。つまりmystring、 とmy_stringは異なります。(Java スタイルのルールに固執する場合、この間違いから大幅に保護されます...)
    • おそらく、「他の場所」で宣言されたものを使用しようとしています。つまり、暗黙のうちにコンパイラに検索を指示した場所とは異なるコンテキストで。(別のクラス? 別のスコープ? 別のパッケージ? 別のコードベース?)
  • 変数を参照する必要がある識別子の場合:

    • 変数の宣言を忘れている可能性があります。
    • おそらく、変数宣言は、使用しようとした時点で範囲外です。(以下の例を参照)
  • メソッド名またはフィールド名である必要がある識別子の場合:

    • おそらく、親/祖先クラスまたはインターフェイスで宣言されていない継承されたメソッドまたはフィールドを参照しようとしています。

    • おそらく、使用している型に存在しない (つまり、宣言されていない) メソッドまたはフィールドを参照しようとしています。例"rope".push()2 .

    • おそらく、メソッドをフィールドとして使用しようとしているか、またはその逆です。例:"rope".lengthまたはsomeArray.length().

    • おそらく、配列要素ではなく配列を誤って操作している可能性があります。例えば

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // maybe that should be 'strings[0].charAt(3)'
      
  • クラス名である必要がある識別子の場合:

    • クラスをインポートするのを忘れた可能性があります。

    • 「スター」インポートを使用した可能性がありますが、インポートしたどのパッケージにもクラスが定義されていません。

    • おそらくあなたは次のようにaを忘れましnewた:

          String s = String();  // should be 'new String()'
      
  • 型またはインスタンスが期待していたメンバー (メソッドまたはフィールドなど) を持っていないように見える場合:

    • おそらく、ネストされたクラスまたはジェネリック パラメーターを宣言して、使用しようとしていた型を隠している可能性があります。
    • おそらく、静的変数またはインスタンス変数をシャドウイングしています。
    • 間違ったタイプをインポートした可能性があります。たとえば、IDE の補完または自動修正によりjava.awt.Listjava.util.List.
    • 間違ったバージョンの API を使用 (コンパイル) している可能性があります。
    • オブジェクトを適切なサブクラスにキャストするのを忘れた可能性があります。
    • おそらく、変数の型を、探しているメンバーを持つ型のスーパータイプとして宣言したのでしょう。

問題は、多くの場合、上記の組み合わせです。たとえば、「スター」を付けてインポートしてから、 notにあるクラスjava.io.*を使用しようとした可能性があります。または、 のクラスである...を書くつもりだったのかもしれません。Filesjava.niojava.ioFilejava.io


以下は、不適切な変数スコープが「シンボルが見つかりません」というエラーにつながる可能性がある例です。

List<String> strings = ...

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

iこれにより、ifステートメントで「シンボルが見つかりません」というエラーが発生します。前に を宣言しましたが、その宣言はステートメントとその本体のスコープ内iのみあります。ステートメント内のへの参照は、 のその宣言を認識できません対象外です。foriifi

(ここでの適切な修正は、ifステートメントをループ内に移動するか、ループiの開始前に宣言することです。)


以下は、タイプミスが一見不可解な「シンボルが見つかりません」というエラーにつながるという困惑を引き起こす例です。

for (int i = 0; i < 100; i++); {
    System.out.println("i is " + i);
}

printlnこれにより、コールiで見つからないというコンパイル エラーが発生します。でも(あなたが言うのを聞いて)私はそれを宣言しました!

問題は、 の前の卑劣なセミコロン ( ;){です。Java 言語の構文では、そのコンテキストのセミコロンを空のステートメントとして定義しています。forその後、空のステートメントがループの本体になります。したがって、そのコードは実際には次のことを意味します。

for (int i = 0; i < 100; i++); 

// The previous and following are separate statements!!

{
    System.out.println("i is " + i);
}

ブロックはループの本体ではないため、ステートメント内の前の宣言はブロック{ ... }内の範囲外ですforifor


タイプミスが原因で発生する「シンボルが見つかりません」エラーの別の例を次に示します。

int tmp = ...
int res = tmp(a + b);

前の宣言にもかかわらず、式のtmpintmp(...)は誤りです。コンパイラは というメソッドを探しますが、tmp見つかりません。以前に宣言さtmpれた は、メソッドの名前空間ではなく、変数の名前空間にあります。

私が遭遇した例では、プログラマーは実際には演算子を省略していました。彼が書きたかったのは次のことです。

int res = tmp * (a + b);

コマンド ラインからコンパイルしている場合に、コンパイラがシンボルを検出できない別の理由があります。他のクラスをコンパイルまたは再コンパイルするのを単に忘れている可能性があります。たとえば、クラスがFooあり、BarwhereFooBar. コンパイルBarしたことがないのに を実行するjavac Foo.javaと、コンパイラがシンボルを見つけられないことがありますBar。簡単な答えは、コンパイルFooしてBarまとめることです。例:javac Foo.java Bar.javaまたはjavac *.java. または、Java ビルド ツールを使用することをお勧めします。Ant、Maven、Gradle など。

他にもいくつかのあいまいな原因があります...以下で扱います。

3. これらのエラーを修正するにはどうすればよいですか?

一般的に言えば、コンパイル エラーの原因を突き止めることから始めます。

  • コンパイル エラー メッセージで示されているファイル内の行を確認します。
  • エラー メッセージがどのシンボルについて話しているかを特定します。
  • コンパイラがシンボルが見つからないと言っている理由を理解してください。上記を参照!

次に、コードが何を言っているのかを考えます。そして最後に、目的を達成するためにソース コードにどのような修正を加える必要があるかを判断します。

すべての「修正」が正しいわけではないことに注意してください。このことを考慮:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

コンパイラが に対して「シンボルが見つかりません」と言ったとしますj。それを「修正」できる方法はたくさんあります。

  • 内側forを変更できますfor (int j = 1; j < 10; j++)-おそらく正しいです。
  • 内側のループまたは外側のループのj にfor 宣言を追加できます - おそらく正しいでしょう。forfor
  • 内側のループで にj変更できます - おそらく間違っています!ifor
  • 等々。

ポイントは、適切な修正を見つけるために、コードが何をしようとしているのかを理解する必要があるということです。

4. 原因不明

「シンボルが見つかりません」が説明できないように見えるいくつかのケースを次に示します...よく見るまで。

  1. 不適切な依存関係: ビルド パスとプロジェクトの依存関係を管理する IDE またはビルド ツールを使用している場合は、依存関係に誤りがある可能性があります。たとえば、依存関係を除外したり、間違ったバージョンを選択したりしました。ビルド ツール (Ant、Maven、Gradle など) を使用している場合は、プロジェクトのビルド ファイルを確認してください。IDE を使用している場合は、プロジェクトのビルド パス構成を確認してください。

  2. シンボル 'var' が見つかりませんvar:古いコンパイラまたは古い--sourceレベルで、ローカル変数の型推論 (つまり、宣言) を使用するソース コードをコンパイルしようとしている可能性があります。はvarJava 10 で導入されました。JDK のバージョンとビルド ファイル、および (これが IDE で発生した場合) IDE の設定を確認してください。

  3. コンパイル/再コンパイルしていない: 新しい Java プログラマーが Java ツール チェーンのしくみを理解していないか、反復可能な「ビルド プロセス」を実装していないことが時々起こります。たとえば、IDE、Ant、Maven、Gradle などを使用します。このような状況では、プログラマーは、コードを適切に再コンパイルしないことなどによって実際に引き起こされる幻想的なエラーを探して、尻尾を追いかけることになる可能性があります。

    この別の例は、(Java 9+) を使用java SomeClass.javaしてクラスをコンパイルおよび実行する場合です。クラスが、コンパイル (または再コンパイル) していない別のクラスに依存している場合、2 番目のクラスを参照する「シンボルを解決できません」というエラーが発生する可能性があります。他のソース ファイルは自動的にコンパイルされません。コマンドのjava新しい「コンパイルして実行」モードは、複数のソース コード ファイルを含むプログラムを実行するようには設計されていません。

  4. 以前のビルドの問題: クラスが欠落している JAR ファイルを生成する方法で、以前のビルドが失敗した可能性があります。ビルド ツールを使用している場合、通常、このようなエラーが発生します。ただし、他の人から JAR ファイルを取得している場合は、それらが適切にビルドされ、エラーに気付くことに依存しています。これが疑われる場合は、 を使用tar -tvfして疑わしい JAR ファイルの内容をリストします。

  5. IDE の問題: IDE が混乱し、IDE のコンパイラが存在するクラスを見つけられない、またはその逆の状況が報告されています。

    • これは、IDE が間違った JDK バージョンで構成されている場合に発生する可能性があります。

    • これは、IDE のキャッシュがファイル システムと同期していない場合に発生する可能性があります。それを修正するIDE固有の方法があります。

    • これは IDE のバグである可能性があります。たとえば、@Joel Costigliola は、Eclipse が Maven の「テスト」ツリーを正しく処理しなかったシナリオについて説明しました。この回答を参照してください。(明らかに、その特定のバグはずっと前に修正されています。)

  6. Android の問題: Android 用にプログラミングしていて、関連する「シンボルが見つかりません」というエラーが発生した場合は、シンボルがファイルによって定義されているRことに注意してください。ファイルが正しく、正しい場所にあること、および対応するクラス ファイルが生成/コンパイルされていることを確認してください。Java シンボルは大文字と小文字が区別されるため、対応する XML ID も大文字と小文字が区別されることに注意してください。Rcontext.xmlcontext.xmlR

    Android のその他のシンボル エラーは、前述の理由による可能性があります。たとえば、依存関係の欠落または誤り、パッケージ名の誤り、特定の API バージョンに存在しないメソッドまたはフィールド、スペル/入力エラーなどです。

  7. システム クラスの非substring表示 : コンパイラが、次のような不明なシンボルであると不平を言うケースを見てきました。

    String s = ...
    String s1 = s.substring(1);
    

    プログラマーが独自のバージョンの を作成しString、彼のバージョンのクラスではsubstringメソッドが定義されていないことが判明しました。SystemScannerおよび他のクラスでこれを行う人を見てきました。

    教訓:共通ライブラリ クラスと同じ名前で独自のクラスを定義しないでください。

    この問題は、完全修飾名を使用して解決することもできます。たとえば、上記の例では、プログラマーは次のように記述できます。

    java.lang.String s = ...
    java.lang.String s1 = s.substring(1);
    
  8. ホモグリフ: ソース ファイルに UTF-8 エンコーディングを使用する場合、同じように見えても、ホモグリフが含まれているため、実際には異なる識別子を持つことができます。詳細については、このページを参照してください。

    これを回避するには、ソース ファイルのエンコーディングを ASCII または Latin-1 に制限し\uxxxx、他の文字には Java エスケープを使用します。


1 -実行時例外またはエラー メッセージにこれが表示される可能性がある場合は、IDE がコンパイル エラーでコードを実行するように構成されているか、アプリケーションが実行時にコードを生成およびコンパイルしています
2 - 土木工学の 3 つの基本原則: 水は上り坂に流れない、厚板は横の方が強い、ロープを押すことはできません

于 2014-09-07T01:12:08.653 に答える
13

Eclipse でこのエラーを取得する 1 つの方法:

  1. でクラスを定義Asrc/test/javaます。
  2. classを使用する別のクラスBを定義します。src/main/javaA

結果: Eclipse はコードをコンパイルしますが、maven は「シンボルが見つかりません」と表示します。

根本的な原因: Eclipse は、メイン ツリーとテスト ツリーに組み合わせたビルド パスを使用しています。残念ながら、Maven が必要とする、Eclipse プロジェクトのさまざまな部分に異なるビルド パスを使用することはサポートされていません。

解決 :

  1. 依存関係をそのように定義しないでください。つまり、この間違いをしないでください。
  2. この間違いを早期に発見できるように、Maven を使用してコードベースを定期的に構築してください。これを行う 1 つの方法は、CI サーバーを使用することです。
于 2016-05-13T10:09:00.420 に答える
4

ビルドでこのエラーが発生し、IDE ではすべて問題ないと表示されている場合は、両方の場所で同じ Java バージョンを使用していることを確認してください。

たとえば、Java 7 と Java 8 では API が異なるため、古い Java バージョンで存在しない API を呼び出すと、このエラーが発生します。

于 2016-03-08T05:58:27.543 に答える
2

私もこのエラーを受けていました。(ググったらこのページにたどり着きました)

問題:プロジェクト A のクラスで定義された静的メソッドを、別のプロジェクト B で定義されたクラスから呼び出していました。次のエラーが発生しました。

error: cannot find symbol

解決策:最初にメソッドが定義されているプロジェクトをビルドしてから、メソッドが呼び出されたプロジェクトをビルドすることで、これを解決しました。

于 2016-09-28T14:59:49.460 に答える
2

人々が上で述べたように、さまざまなシナリオが考えられます。これを解決するのに役立ったことがいくつかあります。

  1. IntelliJ を使用している場合

    File -> 'Invalidate Caches/Restart'

また

  1. 参照されているクラスは別のプロジェクトにあり、その依存関係はプロジェクトの Gradle ビルド ファイルに追加されませんでした。だから私は依存関係を追加しました

    compile project(':anotherProject')

そしてそれはうまくいきました。チッ!

于 2018-08-18T01:45:46.583 に答える