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

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

问题描述

请解释以下有关找不到符号"、无法解析符号"的内容或找不到符号"错误(在 Java 中):

Please explain the following about "Cannot find symbol", "Cannot resolve symbol" or "Symbol not found" errors (in Java):

  • 它们是什么意思?
  • 什么事情会导致它们?
  • 程序员如何修复它们?

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

推荐答案

0.这两个错误有什么区别吗?

不是真的.找不到符号"、无法解析符号"和找不到符号"都是一样的意思.不同的 Java 编译器使用不同的术语.

0. Is there any difference between the two errors?

Not really. "Cannot find symbol", "Cannot resolve symbol" and "Symbol not found" all mean the same thing. Different Java compilers use different phraseology.

首先,这是一个编译错误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:

  • 关键字:如classwhile等.
  • 文字:如 truefalse42'X'"Hi妈妈!".
  • 运算符和其他非字母数字标记:如 +={ 等.
  • 标识符:如 ReaderitoStringprocessEquibalancedElephants 等.
  • 注释和空格.
  • Keywords: like class, while, and so on.
  • Literals: like true, false, 42, '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:

  • 对于一般标识符:

  • For identifiers in general:

  • 也许你拼错了名字;即 StringBiulder 而不是 StringBuilder.Java 不能也不会试图弥补拼写错误或打字错误.
  • 也许你弄错了;即 stringBuilder 而不是 StringBuilder.所有 Java 标识符都区分大小写.
  • 也许您不恰当地使用了下划线;即 mystringmy_string 是不同的.(如果你坚持 Java 风格的规则,你将在很大程度上避免这个错误......)
  • 也许您正在尝试使用声明为其他地方"的东西;即在与您隐式告诉编译器查看的地方不同的上下文中.(不同的类?不同的范围?不同的包?不同的代码库?)
  • 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 refer to variables:

  • 也许你忘记声明变量了.
  • 也许变量声明在您尝试使用它时超出了范围.(见下面的例子)

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

For identifiers that should be method or field names:

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

  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.

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

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. "rope".push()2.

也许您正试图将方法用作字段,反之亦然;例如rope".lengthsomeArray.length().

Perhaps you are trying to use a method as a field, or vice versa; e.g. "rope".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:

  • 也许你忘记导入类了.

  • Perhaps you forgot to import the class.

也许你用过星星"导入,但该类未在您导入的任何包中定义.

Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.

也许你忘记了一个new,例如:

Perhaps you forgot a new as in:

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

对于类型或实例似乎没有您期望的成员(例如方法或字段)的情况:

For cases where type or instance doesn't appear to have the member (e.g. method or field) you were expecting it to have:

  • 也许您声明了一个嵌套类或泛型参数,隐藏您打算使用的类型.
  • 也许您正在隐藏静态或实例变量.
  • 也许你导入了错误的类型;例如由于 IDE 完成或自动更正可能会建议 java.awt.List 而不是 java.util.List.
  • 也许您正在使用(针对)错误版本的 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 may have suggested java.awt.List rather than java.util.List.
  • Perhaps you are using (compiling against) the wrong version of an API.
  • Perhaps you forgot to cast your object to an appropriate subclass.
  • Perhaps you have declared your variable's type to be a supertype of the one with the member you are looking for.

问题往往是上述问题的组合.例如,也许你明星"导入 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()) {
    ...
}

这将给出一个找不到符号"if 语句中 i 的错误.尽管我们之前声明了 i,但该声明仅在 for 语句及其主体的范围内.if 语句中对 i 的引用看不到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.

(此处适当的修正可能是将 if 语句移到循环内,或在循环开始之前声明 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 之前的声明在 for 语句在块中超出范围.

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);


如果您从命令行编译,编译器可能找不到符号还有另一个原因.您可能只是忘记编译或重新编译某个其他类.例如,如果您有 FooBar 类,其中 Foo 使用 Bar.如果你从来没有编译过Bar,你运行了javac Foo.java,你很可能会发现编译器找不到符号Bar.简单的答案是将 FooBar 编译在一起;例如javac Foo.java Bar.javajavac *.java.或者最好还是使用 Java 构建工具;例如Ant、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:

  • 我可以将内部的 for 更改为 for (int j = 1; j <10; j++) - 可能是正确的.
  • 我可以在内部 for 循环或外部 for 循环之前为 j 添加声明 -可能是正确的.
  • 我可以在内部 for 循环中将 j 更改为 i - 可能是错误的!
  • 等等.
  • 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.

找不到符号 'var':您可能正在尝试编译使用局部变量类型推断(即 var 声明)的源代码和较旧的编译器或更旧的 --source 级别.var 是在 Java 10 中引入的.检查您的 JDK 版本和您的构建文件,以及(如果这发生在 IDE 中),IDE 设置.

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.

您没有重新编译:有时会发生这样的情况:新的 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 文件,您就依赖于他们正确构建,并注意到错误.如果您怀疑这一点,请使用 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 described a scenario where Eclipse did not handle a Maven "test" tree correctly: see this answer. (Apparently that particular bug was been fixed a long time ago.)

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 是类似以下内容的未知符号的情况

Hiding 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 版本,而他的类版本没有定义substring 方法.我见过有人用 SystemScanner 和其他类来做到这一点.

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. I've seen people do this with System, Scanner and other classes.

教训:不要使用与公共库类相同的名称定义自己的类!

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

这个问题也可以通过使用全限定名来解决.例如,在上面的例子中,程序员可以这样写:

The problem can also be solved by using the fully qualified names. For example, in the example above, the programmer could have written:

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

  • 同形文字:如果您对源文件使用 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 - 土木工程的三个基本原则:水不会往上流,木板的一侧更坚固,你不能推绳子.


    1 - If, perchance, you do see this in a runtime exception or error message, then either you have configured your IDE to run code with compilation errors, or your application is generating and compiling code .. at runtime.
    2 - The three basic principles of Civil Engineering: water doesn't flow uphill, a plank is stronger on its side, and you can't push on a rope.

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

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