java - “Cannot find symbol”或 “Cannot resolve symbol”错误是什么意思?

标签 java compiler-errors cannot-find-symbol

请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息:

  • 是什么意思?
  • 什么原因可以导致它们?
  • 程序员如何解决它们?

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

    最佳答案

    0.两种错误之间有区别吗?
    并不是的。 “找不到符号”,“无法解析符号”和“找不到符号”都是相同的意思。不同的Java编译器使用不同的措辞。
    1.“找不到符号”错误是什么意思?
    首先,它是编译错误1。这意味着您的Java源代码有问题,或者您的编译方式有问题。
    您的Java源代码包含以下内容:

  • 关键字:像truefalseclasswhile等。
  • 文字:类似于42'X'"Hi mum!"
  • 运算符和其他非字母数字标记:像+={等。
  • 标识符:像ReaderitoStringprocessEquibalancedElephants等。
  • 注释和空格。

  • “找不到符号”错误与标识符有关。编译代码时,编译器需要确定代码中每个标识符的含义。
    “找不到符号”错误表示编译器无法执行此操作。您的代码似乎是指编译器无法理解的内容。
    2.什么会导致“找不到符号”错误?
    首先,只有一个原因。编译器查看了应该定义标识符的所有位置,但找不到该定义。这可能是由多种原因引起的。常见的如下:
  • 对于一般标识符:
  • 也许您拼错了名字;即StringBiulder而不是StringBuilder。 Java无法也不会尝试弥补拼写错误或输入错误。
  • 也许您错了。即stringBuilder而不是StringBuilder。所有Java标识符均区分大小写。
  • 也许您不恰当地使用了下划线。即mystringmy_string不同。 (如果您坚持使用Java样式规则,则将在很大程度上避免出现此错误……)
  • 也许您正在尝试使用被声明为“其他地方”的东西;即在与您隐式告诉编译器查看的位置不同的上下文中。 (不同的类?不同的作用域?不同的包?不同的代码库?)

  • 对于应引用变量的标识符:
  • 也许您忘记了声明变量。
  • 也许变量声明超出了您尝试使用它的范围。 (请参见下面的示例)

  • 对于应为方法或字段名称的标识符:
  • 也许您正在尝试引用在父/祖先类或接口(interface)中未声明的继承方法或字段。
  • 也许您正在尝试引用所使用类型中不存在(即尚未声明)的方法或字段;例如"someString".push() 2。
  • 也许您正在尝试将方法用作字段,反之亦然;例如"someString".lengthsomeArray.length()
  • 也许您错误地对数组而不是数组元素进行了操作;例如
        String strings[] = ...
        if (strings.charAt(3)) { ... }
        // maybe that should be 'strings[0].charAt(3)'
    

  • 对于应为类名的标识符:
  • 也许您忘记了导入该类。
  • 也许您使用了“star”导入,但是在您导入的任何软件包中都没有定义该类。
  • 也许您忘记了new,如下所示:
        String s = String();  // should be 'new String()'
    

  • 对于类型或实例似乎不具有您期望具有的成员的情况:
  • 也许您已经声明了一个嵌套类或一个通用参数,以掩盖您要使用的类型。
  • 也许您正在隐藏静态变量或实例变量。
  • 也许您输入了错误的类型。例如由于IDE完成或自动更正。
  • 也许您正在使用(针对)错误版本的API。
  • 也许您忘记了将对象转换为适当的子类。


  • 问题通常是上述情况的组合。例如,也许您“星形”导入了java.io.*,然后尝试使用Files类...,它在java.nio中而不是java.io中。或者也许您打算编写File ...,它是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语句及其主体的范围内。在i语句中对if的引用看不到i的声明。它超出范围。
    (这里的适当纠正可能是在循环内移动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循环的主体,因此i语句中先前的for声明超出了该块的范围。

    这是由错字引起的“找不到符号”错误的另一个示例。
    int tmp = ...
    int res = tmp(a + b);
    
    尽管有先前的声明,但tmp表达式中的tmp(...)是错误的。编译器将寻找一种称为tmp的方法,但找不到。先前声明的tmp在变量的 namespace 中,而不在方法的 namespace 中。
    在我遇到的示例中,程序员实际上省略了一个运算符。他的意思是这样写的:
    int res = tmp * (a + b);
    

    如果从命令行进行编译,则编译器可能找不到符号还有另一个原因。您可能只是忘了编译或重新编译其他类。例如,如果您有FooBar类,其中Foo使用Bar。如果您从未编译过Bar并运行javac Foo.java,则很可能会发现编译器找不到符号Bar。简单的答案是将FooBar一起编译。例如javac Foo.java Bar.javajavac *.java。或者最好还是使用Java构建工具;例如 Ant ,Maven,Gradle等。
    还有一些其他更晦涩的原因...我将在下面处理。
    3.如何解决这些错误?
    一般来说,首先要弄清楚是什么导致了编译错误。
  • 查看编译错误消息指示的文件中的行。
  • 标识错误消息正在谈论的符号。
  • 弄清楚编译器为什么说找不到符号;为什么?往上看!

  • 然后,您考虑一下您的代码应该说什么。最后,您确定需要对源代码进行哪些更正以执行所需的操作。
    请注意,并非每个“更正”都是正确的。考虑一下:
    for (int i = 1; i < 10; i++) {
        for (j = 1; j < 10; j++) {
            ...
        }
    }
    
    假设编译器为j说“找不到符号”。我可以通过多种方式“修复”该问题:
  • 我可以将内部for更改为for (int j = 1; j < 10; j++)-可能是正确的。
  • 我可以在内部j循环或外部for循环之前添加for的声明-可能正确。
  • 我可以在内部j循环中将i更改为for-可能是错误的!
  • 等。

  • 关键是您需要了解您的代码正在尝试做什么才能找到正确的解决方案。
    4.不清楚的原因
    在某些情况下,“找不到符号”似乎无法解释……直到您仔细观察。
  • 不正确的依赖关系:如果您使用的是IDE或用于管理构建路径和项目依赖关系的构建工具,则可能是错误的依赖关系。例如遗漏了依赖项,或选择了错误的版本。如果您使用的是构建工具(Ant,Maven,Gradle等),请检查项目的构建文件。如果使用的是IDE,请检查项目的构建路径配置。
  • 您没有在重新编译:有时候,新的Java程序员可能不了解Java工具链的工作方式,或者没有实现可重复的“构建过程”。例如使用IDE,Ant,Maven,Gradle等。在这种情况下,程序员最终可能会追尾寻找一个虚幻的错误,该错误实际上是由于未正确地重新编译代码而导致的,等等。
  • 较早的构建问题:较早的构建可能会失败,从而导致JAR文件缺少类。如果使用构建工具,通常会注意到这种故障。但是,如果您从其他人那里获取JAR文件,则取决于它们是否可以正确构建并注意到错误。如果您怀疑这一点,请使用tar -tvf列出可疑JAR文件的内容。
  • IDE问题:人们已经报告了以下情况:他们的IDE感到困惑,并且IDE中的编译器无法找到存在的类……或相反的情况。
  • 如果使用错误的JDK版本配置了IDE,则可能会发生这种情况。
  • 如果IDE的缓存与文件系统不同步,则可能会发生这种情况。有特定于IDE的方法可以解决此问题。
  • 这可能是一个IDE错误。例如,@ Joel Costigliola描述了Eclipse无法正确处理Maven“测试”树的场景:see this answer

  • Android问题:在为Android编程时,您遇到与R相关的“找不到符号”错误,请注意R符号由context.xml文件定义。检查您的context.xml文件正确并且在正确的位置,并且已经生成/编译了相应的R类文件。请注意,Java符号区分大小写,因此相应的XML ID也区分大小写。
    Android上的其他符号错误可能是由于前面提到的原因引起的;例如缺少或不正确的依赖项,错误的程序包名称,特定API版本中不存在的方法或字段,拼写/键入错误等。
  • 重新定义系统类:我已经看到编译器抱怨substring是一个未知符号的情况,如下所示
    String s = ...
    String s1 = s.substring(1);
    
    原来,程序员创建了自己的String版本,而他的类版本未定义substring方法。
    类(class):不要用与通用库类相同的名称来定义自己的类!
  • 象形文字:如果对源文件使用UTF-8编码,则可能具有看起来相同但实际上不同的标识符,因为它们包含同形文字。有关更多信息,请参见this page
    通过将自己限制为ASCII或Latin-1作为源文件编码,并对其他字符使用Java \uxxxx转义符,可以避免这种情况。

    1-如果有可能在运行时异常或错误消息中看到此错误,则说明您已将IDE配置为运行带有编译错误的代码,或者您的应用程序正在运行时生成和编译代码。
    2-土木工程的三个基本原则:水不上山,木板在其侧面更坚固,并且您不能用力压绳子。

    关于java - “Cannot find symbol”或 “Cannot resolve symbol”错误是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33876567/

    相关文章:

    objective-c - 没有选择器的类方法…即使Xcode可以识别该方法

    java - IntelliJ 无法解析符号 "newFixedThreadPool"

    java - 基本java程序找不到符号错误

    java - 无法在 Eclipse 工作区中配置 Web 应用程序项目的运行路径

    Haskell 无法访问的代码错误?

    mongodb - 是什么导致mongodb中的此索引错误?

    java - JOptionPane 找不到符号

    java - Android 上 TextView 中的多个可点击链接

    java StreamTokenizer wordChars() 和 nextToken()

    java - PowerScript "CHOOSE CASE"是否有 Java 等效项?