web-dev-qa-db-ja.com

"シンボルが見つかりません"というコンパイルエラーはどういう意味ですか?

「シンボルが見つかりません」というエラーについて、次のことを説明してください。

  • このエラーはどういう意味ですか?
  • このエラーの原因は何ですか?
  • プログラマーはどのようにこのエラーを修正しますか?

この質問は、Javaでの "シンボルが見つかりません"というコンパイルエラーに関する包括的な質問です。

335
Stephen C

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

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

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

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

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

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

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

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

  • 一般的な識別子の場合:
    • 名前のつづりが間違っている可能性があります。つまり、StringBiulderの代わりにStringBuilderです。 Javaは、スペルミスや入力ミスを補うことはできませんし、補償しようとしません。
    • おそらくあなたは事件を間違えたでしょう。つまり、stringBuilderの代わりにStringBuilderです。すべてのJava識別子は大文字と小文字が区別されます。
    • アンダースコアを不適切に使用した可能性があります。つまり、mystringmy_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()'
      
  • 型またはインスタンスに、予想されるメンバーが含まれていないように見える場合:

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

問題は多くの場合、上記の組み合わせです。たとえば、Java.io.*をインポートして、Filesクラスを使用しようとしました...これはJava.nioではなくJava.ioにあります。または、File ... isJava.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ステートメントとその本体のscope内のみです。 iステートメント内のifへの参照は表示されませんそのiの宣言。 スコープ外です。

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


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

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

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

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

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

// The previous and following are separate statements!!

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

{ ... }ブロックはforループの本体ではないため、iステートメントのforの以前の宣言はout of scope inブロック。


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

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

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

私が出会った例では、プログラマーは実際にオペレーターを除外していました。彼が書いたことはこれでした:

int res = tmp * (a + b);

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

他にもいくつかのあいまいな原因があります...私は以下で対処します。

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

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

  • コンパイルエラーメッセージで示されたファイル内の行を確認します。
  • エラーメッセージが話しているシンボルを特定します。
  • why​​ _を見つけてください。コンパイラは、シンボルを見つけることができないと言っています。上記を参照!

次に、あなたのコードが言っていることについてthinkします。そして最後に、あなたが望むことをするためにあなたのソースコードにどんな修正をする必要があるかを考え出します。

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

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

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

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

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

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. システムクラスの再定義:コンパイラがsubstringが次のような未知のシンボルであると文句を言うケースを見てきました

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

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

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

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

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


1-実行時間の例外またはエラーメッセージにdoが表示される場合、コンパイルエラーでコードを実行するようにIDEを構成しているか、アプリケーションがコードを生成およびコンパイルしています..実行時。

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

368
Stephen C

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

String s = String();

versus

String s = new String();
21
thinkterry

もう1つの「変数が範囲外」の例 /

そのような質問を数回見たことがあるように、たとえそれが feel okのようになっても違法なことのもう1つの例かもしれません。

このコードを見てください:

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

それは無効なコードです。なぜならmessageという名前の変数は、それぞれのスコープの外には見えないからです。この場合、周囲の括弧{}になります。 

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

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

Javaはfree()delete演算子を持っていないので、変数がもはや使われなくなった時を見つけるために変数スコープを追跡することに頼らなければなりません。 

あなたが何か良いことをしたと思ったらそれは特に悪いです。私はこのようなコードを「最適化」した後にこの種のエラーを見ました:

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

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

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

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

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

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

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

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

解決策: 

  1. 依存関係をそのように定義しないでください。つまり、この間違いをしないでください。
  2. Mavenを使用してコードベースを定期的に構築して、この間違いを早期に解決するようにしてください。そのための1つの方法は、CIサーバーを使用することです。
8

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

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

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

今結果を見てください..

enter image description here

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

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

             String name="smith";

             System.out.print(name);
      }
}

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

enter image description here

Okそのエラーをうまく解決しました。同時に、「メソッドを見つけることができない」または「クラスを見つけることができない」という何かの問題が発生した場合、まずクラスまたはメソッドを定義し、それを使用した後 

3
GT_hash

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

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

2
Jonathan Lin

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

もう1つの原因は、Javaバージョンでサポートされていないjdk7 vs 8の方法です。%Java_HOME%を確認してください。 

0
Striker

人々が上述したように様々なシナリオがあり得る。私がこれを解決するのを助けたいくつかのこと。

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

    File -> 'Invalidate Caches/Restart'

OR

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

    compile project(':anotherProject')

そしてそれはうまくいった。 HTH!

0
avp

EclipseのJavaビルドパスが7、8にマッピングされていて、Project pom.xmlでMavenのプロパティJava.versionが7,8よりも高いJavaバージョン(9、10、11など)である場合は、pomで更新する必要があります。 xmlファイル.

Eclipseでは、JavaがJavaバージョン11にマッピングされており、pom.xmlにはJavaバージョン8にマッピングされています。以下のEclipse IDEのステップに従って、EclipseサポートをJava 11に更新してください。 

次のリンクを貼り付けてください http://download.Eclipse.org/Eclipse/updates/4.9-P-builds atWork 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>

最後にプロジェクトとしてデバッグを右クリック - > Maven clean、Mavenビルドステップ

0
pudaykiran

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

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

0
ANIL KUMAR

私もこのエラーを受けていました。 (私はグーグルと私はこのページに導かれました)

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

error: cannot find symbol

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

0
Maria