「シンボルが見つかりません」というエラーについて、次のことを説明してください。
この質問は、Javaでの "シンボルが見つかりません"というコンパイルエラーに関する包括的な質問です。
まず、それはコンパイルエラーです1。これは、がJavaソースコードに問題があること、またはがコンパイル方法に問題があることを意味します。
Javaソースコードは、次のもので構成されています。
true
、false
、class
、while
など。42
および'X'
および"Hi mum!"
など。+
、=
、{
など。Reader
、i
、toString
、processEquibalancedElephants
など。「シンボルが見つかりません」エラーは、識別子に関するものです。コードがコンパイルされると、コンパイラはコード内の各識別子の意味を理解する必要があります。
「シンボルが見つかりません」エラーは、コンパイラがこれを実行できないことを意味します。あなたのコードは、コンパイラが理解していないものを参照しているようです。
最初の注文として、原因は1つだけです。コンパイラーは、識別子shouldが定義されているすべての場所を調べましたが、定義を見つけることができませんでした。これは、いくつかの原因が考えられます。一般的なものは次のとおりです。
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()'
型またはインスタンスに、予想されるメンバーが含まれていないように見える場合:
問題は多くの場合、上記の組み合わせです。たとえば、Java.io.*
をインポートして、Files
クラスを使用しようとしました...これはJava.nio
ではなくJava.io
にあります。または、File
... isを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
ステートメントとその本体の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);
コマンドラインからコンパイルしている場合、コンパイラがシンボルを見つけられない別の理由があります。単に他のクラスをコンパイルまたは再コンパイルするのを忘れているかもしれません。たとえば、Foo
とBar
のクラスがある場合、Foo
はBar
を使用します。 Bar
を一度もコンパイルしたことがなく、javac Foo.Java
を実行した場合、コンパイラはシンボルBar
を見つけられない可能性があります。簡単な答えは、Foo
とBar
を一緒にコンパイルすることです。例えばjavac Foo.Java Bar.Java
またはjavac *.Java
。または、Javaビルドツールを使用することをお勧めします。例えばAnt、Maven、Gradleなど。
他にもいくつかのあいまいな原因があります...私は以下で対処します。
一般的に言って、最初にコンパイルエラーの原因原因を突き止めることから始めます。
次に、あなたのコードが言っていることについてthinkします。そして最後に、あなたが望むことをするためにあなたのソースコードにどんな修正をする必要があるかを考え出します。
すべての「修正」が正しいわけではないことに注意してください。このことを考慮:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
コンパイラがj
に対して「シンボルが見つかりません」と言ったとします。それを「修正」できる方法はたくさんあります。
for
をfor (int j = 1; j < 10; j++)
に変更できました-おそらく正しいでしょう。j
before内側のfor
ループ、または外側のfor
ループの宣言を追加できます-おそらく正しいでしょう。j
ループでi
をfor
に変更できます-おそらく間違っています!ポイントは、正しい修正を見つけるためにコードが何をしようとしているかを理解するためにneedであるということです。
ここに、「シンボルを見つけることができません」がどうやら不可解であるいくつかのケースがあります...詳しく見るまで。
不適切な依存関係:ビルドパスとプロジェクトの依存関係を管理するIDEまたはビルドツールを使用している場合、間違いを犯している可能性があります依存関係あり。例えば依存関係を除外するか、間違ったバージョンを選択しました。ビルドツール(Ant、Maven、Gradleなど)を使用している場合は、プロジェクトのビルドファイルを確認します。 IDEを使用している場合は、プロジェクトのビルドパス構成を確認してください。
再コンパイルしていません:新しいJavaプログラマーがJavaツールチェーンの仕組みを理解していない場合があります。繰り返し可能な「ビルドプロセス」を実装していません。例えばIDE、Ant、Maven、Gradleなどを使用します。このような状況では、プログラマーは、コードを適切に再コンパイルしなかったことなどによって引き起こされる実際にである架空のエラーを探して尾を追いかけることができます...
以前のビルドの問題:以前のビルドが失敗し、クラスが欠落しているJARファイルが作成された可能性があります。ビルドツールを使用している場合、通常、このようなエラーが発生します。ただし、JARファイルを他の誰かから取得している場合は、それらが適切に構築され、エラーに気づくことに依存しています。これが疑われる場合は、tar -tvf
を使用して疑わしいJARファイルの内容をリストします。
IDEの問題:人々はIDEが混乱し、IDE内のコンパイラが存在するクラスを見つけることができない場合を報告しています...または逆の状況。
これは、IDEが誤ったJDKバージョンで構成されている場合に発生する可能性があります。
これは、IDEのキャッシュがファイルシステムと同期しなくなると発生する可能性があります。 IDEを修正する特定の方法があります。
これはIDEバグである可能性があります。たとえば、@ Joel Costigliolaは、EclipseがMavenの「テスト」ツリーを正しく処理しないシナリオを説明しています。 この回答を参照してください 。
システムクラスの再定義:コンパイラがsubstring
が次のような未知のシンボルであると文句を言うケースを見てきました
String s = ...
String s1 = s.substring(1);
プログラマーがString
の独自のバージョンを作成し、クラスの彼のバージョンがsubstring
メソッドを定義していないことが判明しました。
レッスン:一般的なライブラリクラスと同じ名前の独自のクラスを定義しないでください!
ホモグリフ:ソースファイルにUTF-8エンコーディングを使用する場合、lookと同じ識別子を持つことが可能ですが、ホモグリフが含まれているため、実際には異なります。詳細については、 このページ を参照してください。
これを回避するには、ソースファイルエンコーディングとしてASCIIまたはLatin-1に制限し、他の文字にJava \uxxxx
エスケープを使用します。
1-実行時間の例外またはエラーメッセージにdoが表示される場合、コンパイルエラーでコードを実行するようにIDEを構成しているか、アプリケーションがコードを生成およびコンパイルしています..実行時。
2-土木工学の3つの基本原則:水は上り坂に流れず、厚板の側面は強くなり、文字列を押すことはできません。
new
を忘れた場合も、このエラーが発生します。
String s = String();
versus
String s = new String();
もう1つの「変数が範囲外」の例 /
そのような質問を数回見たことがあるように、たとえそれが feel okのようになっても違法なことのもう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()
や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);
Eclipseでこのエラーを取得する1つの方法:
src/test/Java
にクラスA
を定義します。B
を使用する別のクラスA
をsrc/main/Java
に定義します。結果:Eclipseはコードをコンパイルしますが、mavenは "シンボルが見つかりません"と表示します。
根本的な原因:Eclipseはメインツリーとテストツリーに組み合わせたビルドパスを使用しています。残念ながら、Eclipseプロジェクトのさまざまな部分に異なるビルドパスを使用することはサポートされていません。これはMavenが必要としているものです。
解決策:
「見つけられない」とは、適切な変数、メソッド、クラスなどを見つけられないコンパイラ、つまり、そのエラーメッセージが表示された場合、まずエラーメッセージが表示されるコード行を検索したいということです。使用前にどの変数、メソッド、またはクラスが定義されていないかを見つけることができます。確認後、その変数、メソッド、またはクラスを後で使用するために使用できるように初期化してください。
デモクラスを作成して名前を印刷します。
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そのエラーをうまく解決しました。同時に、「メソッドを見つけることができない」または「クラスを見つけることができない」という何かの問題が発生した場合、まずクラスまたはメソッドを定義し、それを使用した後
IDEがすべて問題ないことを示している間に、別の場所でこのエラーが発生した場合は、両方の場所で同じJavaバージョンを使用していることを確認してください。
たとえば、Java 7とJava 8には異なるAPIがあるため、古いバージョンのJavaで存在しないAPIを呼び出すとこのエラーが発生します。
ヒントについては、エラーをスローするクラス名nameと行番号をよく見てください。例:コンパイル失敗 [ERROR]\applications\xxxxx.Java:[44,30] error:シンボルを見つけることができません
もう1つの原因は、Javaバージョンでサポートされていないjdk7 vs 8の方法です。%Java_HOME%を確認してください。
人々が上述したように様々なシナリオがあり得る。私がこれを解決するのを助けたいくつかのこと。
IntelliJを使用している場合
File -> 'Invalidate Caches/Restart'
OR
参照されているクラスが別のプロジェクトにあり、その依存関係が私のプロジェクトのGradleビルドファイルに追加されていません。だから私はを使用して依存関係を追加しました
compile project(':anotherProject')
そしてそれはうまくいった。 HTH!
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ビルドステップ
maven compileを使用してコードをコンパイルしてから、maven testを使用して実行しました。コードで何かを変更し、コンパイルせずに実行すると、このエラーが発生します。
解決策:再度コンパイルして、テストを実行します。私にとっては、このように機能しました。
私もこのエラーを受けていました。 (私はグーグルと私はこのページに導かれました)
問題: 他のプロジェクトBで定義されているクラスから、プロジェクトAのクラスで定義されている静的メソッドを呼び出していました。
error: cannot find symbol
解決策: メソッドが定義されているプロジェクトを最初にビルドし、次にメソッドが呼び出されていたプロジェクトをビルドしてこれを解決しました。