什么是“找不到符号”?或“无法解析符号”错误是什么意思? [英] What does a "Cannot find symbol" or "Cannot resolve symbol" error mean?

查看:212
本文介绍了什么是“找不到符号”?或“无法解析符号”错误是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请解释以下有关找不到符号和无法解析符号的错误:

Please explain the following about "Cannot find symbol" and "Cannot resolve symbol" errors:


  • 它们是什么意思?
  • 什么东西会导致它们?

  • 程序员如何着手解决它们?

该问题旨在对Java中的这些常见编译错误进行全面的问答。

推荐答案

0。这两个错误之间有什么区别吗?



不是真的。 找不到符号和无法解析符号含义相同。一些Java编译器使用一个短语,而另一些使用。

0. Is there any difference between the two errors?

Not really. "Cannot find symbol" and "Cannot resolve symbol" mean the same thing. Some Java compilers use one phrase, and some the other one.

首先,它是编译错误 1 。这意味着 或您的Java源代码都有问题,或者的编译方式有问题。

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

您的Java源代码包含以下内容:

Your Java source code consists of the following things:


  • 关键字:类似 true false ,依此类推。

  • 文字:例如 42 'X'妈妈!

  • 运算符和其他非字母数字标记:例如 + = {等。

  • 标识符:例如阅读器 i toString processEquibalancedElephants ,依此类推。

  • 注释和空格。

  • Keywords: like true, false, class, while, and so on.
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
  • Identifiers: like Reader, i, toString, processEquibalancedElephants, and so on.
  • Comments and whitespace.

找不到符号错误与标识符有关。编译代码时,编译器需要确定代码中每个标识符的含义。

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

找不到符号错误表示编译器无法执行此操作。您的代码似乎是指编译器无法理解的内容。

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

作为一阶命令,只有一个原因。编译器查看了应该定义标识符 的所有位置,但找不到该定义。这可能是由多种原因引起的。常见的如下:

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:


  • 对于一般标识符:


    • 也许您拼错了名字;即 StringBiulder 而不是 StringBuilder 。 Java无法也不会尝试弥补拼写错误或键入错误。

    • 也许您弄错了;即 stringBuilder 而不是 StringBuilder 。所有的Java标识符都是区分大小写的。

    • 也许您下划线使用不当;即 mystring my_string 是不同的。 (如果您坚持使用Java样式规则,则将在很大程度上避免出现此错误……)

    • 也许您正在尝试使用被声明为其他地方的东西;即在与您隐式告诉编译器查看的位置不同的上下文中。 (不同的类?不同的作用域?不同的包?不同的代码库?)

    • For identifiers in general:
      • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
      • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
      • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
      • Perhaps you are trying to use something that was declared "somewhere else"; i.e. in a different context to where you have implicitly told the compiler to look. (A different class? A different scope? A different package? A different code-base?)

      • 也许您忘了声明变量。

      • 也许变量声明超出了您的定义范围尝试使用它。 (请参见下面的示例)

      对于应为方法或字段名称的标识符:

      For identifiers that should be method or field names:


      • 也许您试图引用在父/祖先类或接口中未声明的继承方法或字段。

      • 也许您正在尝试引用所使用的类型中不存在(即尚未声明)的方法或字段;例如 someString .push() 2

      • 也许您正在尝试将方法用作领域,反之亦然;例如 someString .length someArray.length()

      • 也许您错误地对数组而不是数组元素进行操作;例如

      • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
      • Perhaps you are trying to refer to a method or field that does not exist (i.e. has not been declared) in the type you are using; e.g. "someString".push()2.
      • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
      • Perhaps you are mistakenly operating on an array rather than array element; e.g.

      String strings[] = ...
      if (strings.charAt(3)) { ... }
      // maybe that should be 'strings[0].charAt(3)'
      


    • 对于应为类名的标识符:

      For identifiers that should be class names:


      • 也许您忘记了

      • 也许您使用了星号导入,但是在您导入的任何软件包中都没有定义该类。

      • 也许您忘记了新的 ,例如:

      String s = String();  // should be 'new String()'
      


      对于类型或实例似乎没有您所期望的成员的情况,

      For cases where type or instance doesn't appear to have the member you were expecting it to have:


      • 也许声明了嵌套类或通用参数,它们遮盖了您要使用的类型。

      • 也许您正在遮盖静态变量或实例变量。

      • 也许您输入了错误的类型;例如由于IDE的完成或自动更正。

      • 也许您正在使用(针对错误版本的API进行编译)。

      • 也许您忘记了将对象转换为适当的子类。

      • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
      • Perhaps you are shadowing a static or instance variable.
      • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
      • Perhaps you are using (compiling against) the wrong version of an API.
      • Perhaps you forgot to cast your object to an appropriate subclass.

      问题通常是以上。例如,也许您星级导入了 java.io。* ,然后尝试使用 Files 类。 。位于 java.nio 中,而不是 java.io 中。也许您是想编写 File ...,而 java.io 。

      The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

      下面是一个示例,该示例说明了错误的变量作用域如何导致找不到符号错误:

      Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

      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 的引用无法看到 <$ c $的声明c> i 。它是超出范围

      This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

      (此处的适当修正可能是将如果在循环内声明,或在循环开始前声明 i 。)

      (An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

      这是一个引起困惑的示例,其中的错字导致看似莫名的找不到符号错误:

      Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

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

      这将使您在 println中出现编译错误呼叫说找不到 i 。但是(我听到你说)我确实声明过!

      This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

      问题是之前的狡猾的分号(; {。 Java语言语法在该上下文中将分号定义为空语句。然后,空语句成为 for 循环的主体。因此该代码实际上意味着:

      The problem is the sneaky semicolon ( ; ) before the {. The Java language syntax defines a semicolon in that context to be an empty statement. The empty statement then becomes the body of the for loop. So that code actually means this:

      for (int i = 0; i < 100; i++); 
      
      // The previous and following are separate statements!!
      
      {
          System.out.println("i is " + i);
      }
      

      {...} 块不是 for 循环的主体,因此 i 之前的声明在<$

      The { ... } block is NOT the body of the for loop, and therefore the previous declaration of i in the for statement is out of scope in the block.

      这是由错字引起的找不到符号错误的另一个示例。

      Here is another example of "Cannot find symbol" error that is caused by a typo.

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

      尽管上一个声明中的 tmp tmp(...)表达式是错误的。编译器将寻找一种名为 tmp 的方法,但找不到。先前声明的 tmp 在变量的名称空间中,而不在方法的名称空间中。

      Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

      在示例中整个过程中,程序员实际上已经省略了一个运算符。他的意思是这样:

      In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

      int res = tmp * (a + b);
      






      还有另一个原因导致编译器找不到如果从命令行编译,则为符号。您可能只是忘了编译或重新编译其他类。例如,如果您有类 Foo Bar ,其中 Foo 使用 Bar 。如果您从未编译过 Bar 并且运行了 javac Foo.java ,则很容易发现编译器可以找不到符号 Bar 。简单的答案是将 Foo Bar 一起编译;例如 javac Foo.java Bar.java javac * .java 。或者最好还是使用Java构建工具;例如蚂蚁,Maven,Gradle等。


      There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to compile Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

      还有其他一些更晦涩的原因……我将在下面处理。

      There are some other more obscure causes too ... which I will deal with below.

      通常来说,您首先要弄清楚是什么引起的编译错误。

      Generally speaking, you start out by figuring out what caused the compilation error.


      • 查看由编译错误消息指示的文件中的行。

      • 确定该错误消息在说哪个符号

      • 找出为什么,编译器说找不到符号;

      • Look at the line in the file indicated by the compilation error message.
      • Identify which symbol that the error message is talking about.
      • Figure out why the compiler is saying that it cannot find the symbol; see above!

      然后您思考您的代码应该说什么。然后,最后您确定需要对源代码进行哪些更正以执行所需的操作。

      Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

      请注意,并非每个更正都是正确的。考虑以下情况:

      Note that not every "correction" is correct. Consider this:

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

      假设编译器为 j 说找不到符号。我可以通过多种方式修复该问题:

      Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:


      • 我可以将内部更改为(int j = 1; j< 10; j ++)-可能是正确的。

      • 我可以添加一个声明对于 j 之前,内部 for 循环,或外部 for 循环-可能正确。

      • 我可以将 j 更改为 i 在内部 for 循环-可能是错误的!

      • ,依此类推。

      • I could change the inner for to for (int j = 1; j < 10; j++) - probably correct.
      • 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.

      在某些情况下,找不到符号似乎无法解释……直到您仔细观察为止。

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


      1. 不正确的依赖项:如果您使用的是IDE或用于管理构建路径和项目依赖项的构建工具,则可能错误的依赖关系;例如遗漏了依赖项,或选择了错误的版本。如果您使用的是构建工具(Ant,Maven,Gradle等),请检查项目的构建文件。如果您使用的是IDE,请检查项目的构建路径配置。

      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.

      您没有重新编译:有时会发生新的Java程序员不了解Java工具链的工作方式,或者没有实现可重复的构建过程。例如使用IDE,Ant,Maven,Gradle等。在这种情况下,程序员最终可能会追逐自己的尾巴,以查找实际上是由于错误地重新编译代码而导致的 虚幻错误,等等。

      You are not 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 ...

      较早的构建问题:较早的构建可能会失败,从而导致JAR文件缺少类。如果使用构建工具,通常会注意到这种故障。但是,如果要从其他人那里获取JAR文件,则必须依靠 them 正确构建并注意到错误。如果您怀疑,请使用 tar -tvf 列出可疑JAR文件的内容。

      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.

      IDE问题:人们报告了以下情况:IDE混乱,IDE中的编译器找不到存在的类...或相反的情况。

      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.


      • 如果IDE配置了错误的JDK版本,则可能会发生这种情况。

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

      如果IDE的缓存与文件系统不同步,则可能发生这种情况。有一些特定于IDE的方法可以解决此问题。

      This could happen if the IDE's caches get out of sync with the file system. There are IDE specific ways to fix that.

      这可能是一个IDE错误。例如,@ Joel Costigliola描述了Eclipse无法正确处理Maven测试树的情况: 查看此答案

      This could be an IDE bug. For instance @Joel Costigliola describes a scenario where Eclipse does not handle a Maven "test" tree correctly: see this answer.

      Android问题:在编程时对于Android,并且您有与 R 相关的找不到符号错误,请注意,已定义 R 符号通过 context.xml 文件。检查您的 context.xml 文件是否正确并且在正确的位置,以及相应的 R 类文件是否已被保存。生成/编译。请注意,Java符号区分大小写,因此相应的XML ID也区分大小写。

      Android issues: When you are programming for Android, and you have "Cannot find symbol" errors related to R, be aware that the R symbols are defined by the context.xml file. Check that your context.xml file is correct and in the correct place, and that the corresponding R class file has been generated / compiled. Note that the Java symbols are case sensitive, so the corresponding XML ids are be case sensitive too.

      Android上的其他符号错误很可能是由于前面提到的原因引起的;例如缺少或不正确的依赖项,错误的程序包名称,特定API版本中不存在的方法或字段,拼写/键入错误等。

      Other symbol errors on Android are likely to be due to previously mention reasons; e.g. missing or incorrect dependencies, incorrect package names, method or fields that don't exist in a particular API version, spelling / typing errors, and so on.

      重新定义系统类:我曾经看到编译器抱怨 substring 是一个未知符号的情况,类似以下内容

      Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

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

      事实证明,程序员创建了自己的 String版本并且他的课程版本未定义子字符串方法。

      It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

      课程:不要用与通用库类相同的名称来定义自己的类!

      Lesson: Don't define your own classes with the same names as common library classes!

      同形文字::如果您使用UTF-8编码对于您的源文件,可能具有外观相同的标识符,但实际上是不同的,因为它们包含同形文字。有关更多信息,请参见此页面

      Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

      通过将自己限制为ASCII或Latin-1作为源文件编码,并使用Java \uxxxx 转义为其他字符。

      You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.






      1 -如果,也许您在运行时异常或错误消息中看到了此消息,则说明您已将IDE配置为运行带有编译错误的代码,或者您的应用程序正在运行时生成和编译代码。 。

      2-土木工程的三个基本原则:水不上坡,木板更坚固,您不能按下字符串

      这篇关于什么是“找不到符号”?或“无法解析符号”错误是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆