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

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

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

  • それらはどういう意味ですか?
  • 何が原因となるのでしょうか?
  • プログラマーはどうやってそれらを修正するのでしょうか?

この質問は、Java の一般的なコンパイル エラーに関する包括的な Q&A を提供することを目的としています。

ベストアンサー1

0. これらのエラーには違いがありますか?

そうではありません。「シンボルが見つかりません」、「シンボルを解決できません」、「シンボルが見つかりません」はすべて同じ意味です。(異なる Java コンパイラは異なる人によって書かれており、同じことを言うのに異なる人が異なる言い回しを使います。)

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

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

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

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

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

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

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

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

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

    • 名前のスペルが間違っている可能性があります。つまり、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)'
      
  • クラス名となる識別子の場合:

    • おそらくクラスをインポートし忘れたのでしょう。

    • おそらく「スター」インポートを使用しましたが、インポートしたどのパッケージにもクラスが定義されていません。

    • おそらく、次のように忘れたのでしょうnew:

          String s = String();  // Should be 'new String()'
      
    • おそらく、デフォルト パッケージ(つまり、ステートメントのないクラスが配置されるパッケージ)で宣言されているクラスをインポートまたは使用しようとしている可能性がありますpackage

      ヒント: パッケージについて学習してください。 1 つのクラス、または 1 つの Java ソース ファイルで構成される単純なアプリケーションにのみ、デフォルト パッケージを使用する必要があります。

  • 型またはインスタンスに、期待していたメンバー (メソッドやフィールドなど) が存在しないと思われる場合は、次のようになります。

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

問題は、多くの場合、上記の組み合わせです。たとえば、インポートjava.io.*後に、Filesではないクラス ...java.nioを使用しようとした可能性があります。または、のクラスである...java.ioと記述した可能性があります。Filejava.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への参照は、の宣言を参照できません。 はスコープ外ですiifi

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

前の宣言にもかかわらず、tmp式の はtmp(...)エラーです。コンパイラは と呼ばれるメソッドを検索しますtmpが、見つかりません。前に宣言された は、tmpメソッドの名前空間ではなく、変数の名前空間にあります。

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

int res = tmp * (a + b);

コマンドラインからコンパイルする場合、コンパイラがシンボルを見つけられない理由は他にもあります。単に他のクラスをコンパイルまたは再コンパイルし忘れただけかもしれません。たとえば、 が を使用するクラスFooBarがあるとします。コンパイルしたことがなくを実行すると、コンパイラがシンボル を見つけられない可能性があります。簡単な答えは、と を一緒にコンパイルすることです。たとえば、または です。あるいは、Java ビルド ツールを使用する方がよいでしょう。たとえば、FooBarBarjavac Foo.javaBarFooBarjavac Foo.java Bar.javajavac *.javaメイヴングラドル等々。

他にももっとわかりにくい原因がいくつかありますが、それについては後ほど説明します。

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

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

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

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

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

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

コンパイラが に対して「シンボルが見つかりません」と表示したとしますj。これを「修正」する方法は多数あります。

  • 内側を - おそらく正しい -forに変更することができますfor (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!
  • and so on.

The point is that you need to understand what your code is trying to do in order to find the right fix.

4. Obscure causes

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

  1. Incorrect dependencies: If you are using an IDE or a build tool that manages the build path and project dependencies, you may have made a mistake with the dependencies; e.g., left out a dependency, or selected the wrong version. If you are using a build tool (Ant, Maven, Gradle, etc), check the project's build file. If you are using an IDE, check the project's build path configuration.

  2. Cannot find symbol 'var': You are probably trying to compile source code that uses local variable type inference (i.e. a var declaration) with an older compiler or older --source level. The var was introduced in Java 10. Check your JDK version and your build files, and (if this occurs in an IDE), the IDE settings.

  3. You are not compiling / recompiling: It sometimes happens that new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like.

    Another example of this is when you use (Java 9+) java SomeClass.java to compile and run a class. If the class depends on another class that you haven't compiled (or recompiled), you are liable to get "Cannot resolve symbol" errors referring to the 2nd class. The other source file(s) are not automatically compiled. The java command's new "compile and run" mode is not designed for running programs with multiple source code files.

  4. An earlier build problem: It is possible that an earlier build failed in a way that gave a JAR file with missing classes. Such a failure would typically be noticed if you were using a build tool. However if you are getting JAR files from someone else, you are dependent on them building properly, and noticing errors. If you suspect this, use tar -tvf to list the contents of the suspect JAR file.

  5. IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

    • This could happen if the IDE has been configured with the wrong JDK version.

    • これは、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 つの基本原則土木工学水は上流には流れず、板は横の方が強く、ロープを押すこともできません

おすすめ記事