「シンボルが見つかりません」または「シンボルを解決できません」というエラーはどういう意味ですか?


395

「シンボルが見つかりません」および「シンボルを解決できません」のエラーについて、以下について説明してください。

  • 彼らはどういう意味ですか?
  • 何が原因でしょうか?
  • プログラマはそれらをどのように修正しますか?

この質問は、Javaでのこれらの一般的なコンパイルエラーに関する包括的なQ&Aを作成するためのものです。

回答:


417

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

あんまり。「シンボルが見つかりません」と「シンボルを解決できません」は同じ意味です。一部のJavaコンパイラは1つの句を使用し、一部は他の句を使用します。

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

まず、これはコンパイルエラーです1。それは意味のいずれかの Javaソースコードに問題がある、またはあなたがそれをコンパイルしているというやり方に問題があります。

Javaソースコードは次の要素で構成されています。

  • キーワード:のようなtruefalseclasswhile、など。
  • リテラル:42および'X'およびのような"Hi mum!"
  • 演算子と英数字以外のトークン:のような+={、など。
  • 識別子:のようなReaderitoStringprocessEquibalancedElephants、など。
  • コメントと空白。

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

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

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

最初の注文として、原因は1つだけです。コンパイラは、識別子定義する必要があるすべての場所を調べましたが、定義を見つけることができませんでした。これにはいくつかの原因が考えられます。一般的なものは次のとおりです。

  • 一般的な識別子の場合:
    • おそらく、名前のスペルを間違えたかもしれません。つまりのStringBiulder代わりにStringBuilder。Javaは、スペルミスや入力ミスを補うことはできません。
    • たぶん、あなたはケースを間違えました。つまりのstringBuilder代わりにStringBuilder。すべてのJava識別子は大文字と小文字を区別します。
    • アンダースコアを不適切に使用した可能性があります。つまりmystring、とmy_stringは異なります。(Javaスタイルのルールに固執すれば、この間違いからほぼ保護されます...)
    • おそらく、「どこか別の場所」と宣言されたものを使用しようとしています。つまり、コンパイラに探すように暗黙的に指示した場所とは異なるコンテキストで。(異なるクラス?異なるスコープ?異なるパッケージ?異なるコードベース?)
  • 変数を参照する必要がある識別子の場合:
    • おそらく、変数を宣言するのを忘れていました。
    • おそらく、変数宣言は、使用しようとした時点でスコープ外です。(下の例を参照)
  • メソッド名またはフィールド名であるべき識別子の場合:

    • おそらく、親/祖先のクラスまたはインターフェースで宣言されていない継承されたメソッドまたはフィールドを参照しようとしている可能性があります。
    • おそらく、使用している型に存在しない(つまり、宣言されていない)メソッドまたはフィールドを参照しようとしている可能性があります。例"someString".push()2
    • おそらく、メソッドをフィールドとして使用しようとしている、またはその逆です。たとえば"someString".lengthまたはsomeArray.length()
    • おそらく、配列要素ではなく配列を誤って操作している可能性があります。例えば

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

    • クラスをインポートするのを忘れたのかもしれません。
    • 「スター」インポートを使用した可能性がありますが、インポートしたパッケージのいずれにもクラスが定義されていません。
    • 多分あなたはのnewように忘れました:

      String s = String();  // should be 'new String()'
  • タイプまたはインスタンスに、予期したメンバーが含まれていないと思われる場合:

    • おそらく、使用するつもりだった型を隠すネストされたクラスまたはジェネリックパラメーターを宣言しました。
    • おそらく、静的変数またはインスタンス変数をシャドーイングしています。
    • おそらく、間違ったタイプをインポートしました。たとえば、IDEの完了または自動修正が原因です。
    • おそらく、間違ったバージョンのAPIを使用(コンパイル)しています。
    • おそらく、オブジェクトを適切なサブクラスにキャストするのを忘れていました。

多くの場合、問題は上記の組み合わせです。たとえば、「スター」をインポートjava.io.*してから、Filesクラス…を使用しようとした可能性がjava.nioありjava.ioます。あるいは、あなたが書くつもりだったかもしれませんFile...これのクラスですjava.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、その宣言はステートメントとその本文のスコープ内にのみありますfor。ステートメントi内のへの参照では、そのの宣言を見ることができません。それは適用範囲外ifi

(ここでの適切な修正は、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);
}

{ ... }ブロックは、本体ではありませんforループ、そのための前の宣言iforステートメントがあるスコープ外ブロックで。


これは、タイプミスが原因の「シンボルが見つかりません」エラーの別の例です。

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

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

私が遭遇した例では、プログラマーは実際にはオペレーターを省いていた。彼が書くつもりだったのはこれです:

int res = tmp * (a + b);

コマンドラインからコンパイルしている場合、コンパイラがシンボルを見つけられない場合があるもう1つの理由があります。他のクラスをコンパイルまたは再コンパイルするのを忘れただけかもしれません。たとえば、クラスがFooあり、BarがをFoo使用している場合Bar。コンパイルしたことがなく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 前に宣言を追加できます-おそらく正しいです。forfor
  • 私は、変更される可能性ji、内側にforループ-おそらく間違っています!
  • 等々。

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

4.あいまいな原因

ここでは、「シンボルが見つかりません」が不可解なように見えるいくつかのケースを示します...よく見るまで。

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

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

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

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

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

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

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

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

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

  6. システムクラスの再定義:コンパイラsubstringが次のような未知のシンボルであると文句を言う場合を見てきました。

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

    プログラマーがの独自のバージョンを作成しString、クラスの彼のバージョンはsubstringメソッドを定義していないことがわかりました。

    レッスン:一般的なライブラリクラスと同じ名前で独自のクラスを定義しないでください。

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

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


1 -もし、恐らく、あなたはない、あなたはコンパイルエラーでコードを実行するために、あなたのIDEを設定している、またはアプリケーションが生成し、実行時に...コードをコンパイルされるか、実行時例外やエラーメッセージにこれを参照してください。

2-土木工学の3つの基本原則:水は上り坂を流れず、厚板はその側が強く、紐を押すことはできません


Eclipseが問題を認識していないときにこのコンパイルエラーが発生する別の状況がありました。依存関係がそれぞれ他のクラスで定義されている2つのクラスです。私の場合、私は愚かにもすでにその列挙型を使用していたクラスで定義されたインターフェースを実装する列挙型を持っていました。
Jogi、2016年

上記のコメントと多少似ていますが、Eclipseからプログラムをコンパイルして実行しても問題はありません。コンソールからコンパイルすると、インポートの最後の要素に関連する「シンボルが見つかりません」エラーが発生します。コードには実際には何も問題がないので、何が原因なのかはわかりません。
Andres Stadelmann、2016年

別の問題は、IDEが他のエラーをこのカテゴリに「解釈」する可能性があることです。たとえばprintlnSystem.out.println、標準のコンパイラの下のクラスレベルに置いたら私達与えるだろう<identifier> expectedデモ)が、IntelliJの中で我々が表示されますCannot resolve symbol 'println'デモを)。
Pshemo

ワオ。私はそれをコンパイラのバグと呼びます。
スティーブンC

23

を忘れた場合にも、このエラーが発生しますnew

String s = String();

String s = new String();

newキーワードなしの呼び出しは、String引数なしで呼び出された(ローカル)メソッドを探して探すため、そのメソッドシグネチャはおそらく定義されていません。


14

「変数は範囲外です」のもう1つの例

この種の質問をすでに何度か見てきたので、たとえ大丈夫だと思っていても違法なもののもう1つの例を示します。

このコードを考えてみましょう:

if(somethingIsTrue()) {
  String message = "Everything is fine";
} else {
  String message = "We have an error";
}
System.out.println(message);

これは無効なコードです。というのも、指定された変数messageはどちらも、それぞれのスコープの外には表示されません{}

「しかし、messageという名前の変数はどちらかの方法で定義されているため、message if "の後に定義されます。

しかし、あなたは間違っているでしょう。

Javaにはfree()or delete演算子がないため、変数が使用されなくなった時期を(これらの原因の変数への参照と共に)追跡するために変数スコープを追跡する必要があります。

何か良いことをしたと思った場合は特に悪いことです。次のようなコードを「最適化」した後、この種のエラーが発生しました。

if(somethingIsTrue()) {
  String message = "Everything is fine";
  System.out.println(message);
} else {
  String message = "We have an error";
  System.out.println(message);
}

「ああ、重複したコードがあるので、その共通の行を引き出しましょう」->そして、それです。

この種のスコープの問題に対処する最も一般的な方法は、else-valuesを外部スコープの変数名に事前に割り当て、次の場合に再割り当てすることです。

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);

4
「Javaにはfree()またはdelete演算子がないため、変数が使用されなくなったときを(これらの原因の変数への参照と共に)追跡するために変数スコープを追跡する必要があります。」-本当ですが、これは関係ありません。CとC ++にはそれぞれfree / delete演算子がありますが、例と同等のC / C ++コードは違法です。CおよびC ++ブロックは、Javaと同様に変数のスコープを制限します。実際、これはほとんどの「ブロック構造」言語に当てはまります。
スティーブンC

1
すべてのブランチで異なる値を割り当てるコードのより良い解決策は、空白のfinal変数宣言を使用することです。
Daniel Pryden

10

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

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

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

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

解決 :

  1. このように依存関係を定義しないでください。つまり、この間違いをしないでください。
  2. Mavenを使用してコードベースを定期的にビルドし、この間違いを早期に発見できるようにします。これを行う1つの方法は、CIサーバーを使用することです。

これに対する解決策は何ですか?

2
src / main / javaで使用するものはすべて、src / main / javaまたはコンパイル/ランタイムの依存関係(テストの依存関係ではない)で定義する必要があります。
Joel Costigliola、2016年

5

「見つかりません」とは、適切な変数、メソッド、クラスなどを見つけられないコンパイラがエラーメッセージを受け取った場合、まず最初に、エラーメッセージを受け取るコード行を見つけます。それを使用する前に、どの変数、メソッド、またはクラスが定義していないかを見つけることができます。確認後、その変数、メソッド、またはクラスを初期化して、後でrequire ...次の例を検討してください。

デモクラスを作成して名前を印刷します...

class demo{ 
      public static void main(String a[]){
             System.out.print(name);
      }
}

結果を見てください。

ここに画像の説明を入力してください

そのエラーは、「変数名が見つかりません」と言います。「 'name」変数の値の定義と初期化は、そのエラーを廃止できます。

class demo{ 
      public static void main(String a[]){

             String name="smith";

             System.out.print(name);
      }
}

新しい出力を見てください...

ここに画像の説明を入力してください

Okはそのエラーを正常に解決しました。同時に、「メソッドが見つかりません」または「クラスが見つかりません」という問題が発生した場合は、最初にクラスまたはメソッドを定義し、それを使用します。


3

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

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


2

私もこのエラーを受け取りました。(私はググってこのページにリダイレクトされました)

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

error: cannot find symbol

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


はい、これはたとえば、再利用可能な関数を現在のパッケージから一般的なutilsパッケージに移動することを決定した場合に発生する可能性がありますが、現在のパッケージから関数を呼び出す前に一般的なパッケージをコンパイルするのを忘れています。
buildingKofi

2

日食Javaビルドパスが7、8にマップされ、プロジェクトpom.xmlでMavenプロパティjava.versionが7,8より高いJavaバージョン(9、10、11など)と記載されている場合、pomで更新する必要があります。 xmlファイル。

Eclipseでは、JavaがJavaバージョン11にマッピングされ、pom.xmlでJavaバージョン8にマッピングされます。EclipseIDEヘルプ->新しいソフトウェアのインストール->の以下の手順を実行して、EclipseサポートをJava 11に更新します。

次のリンクを貼り付けhttp://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With

または

追加(ポップアップウィンドウが開きます)->

Name:Java 11のサポート Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

次に、以下のようにpom.xmlファイルのMavenプロパティのJavaバージョンを更新します

<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

最後にプロジェクトを右クリックして、Debug as-> Maven clean、Maven build stepsを実行します


2

解決した

[ ビルド] -> [ プロジェクトの再ビルド]を選択して解決します


1
それは非常に依存し、通常はそうではありません。
Maarten Bodewes、

1

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

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

    File -> 'Invalidate Caches/Restart'

または

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

    compile project(':anotherProject')

そしてそれは働いた。HTH!


1

maven compileを使用してコードをコンパイルし、次にmaven testを使用してそれを実行しました。コードで何かを変更し、コンパイルせずに実行していると、このエラーが発生します。

解決策:もう一度コンパイルして、テストを実行します。私にとっては、このように機能しました。


1

私の場合-以下の操作を実行する必要がありました:

  1. 移動context.xmlからファイルをsrc/java/packageするresourceディレクトリ(IntelliJのIDE)
  2. クリーンtargetディレクトリ。

参照を気にせずにファイルを移動すると、このエラーが発生する可能性があります。私はすでにこれに会った。Gitをリセットして慎重にもう一度移動するだけで、エラーが解決します。
HuyHómHỉnh19年

0

ヒントについては、エラーをスローするクラス名と行番号を詳しく見てください。例:コンパイル失敗[ERROR] \ applications \ xxxxx.java:[44,30]エラー:シンボルが見つかりません

もう1つの原因は、jdk7と8のJavaバージョンのサポートされていないメソッドです。%JAVA_HOME%を確認してください


これは、他の答えが言うのと同じことを言っているだけです。
スティーブンC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.