首页 文章

“无法找到符号”编译错误是什么意思?

提问于
浏览
301

请解释以下关于“无法找到符号”的错误:

  • 这个错误是什么意思?

  • 什么东西会导致这个错误?

  • 程序员如何解决此错误?

这个问题旨在成为关于Java中"cannot find symbol"编译错误的综合问题 .

10 回答

  • 3

    可能存在人们上面提到的各种场景 . 一些帮助我解决这个问题的事情 .

    • 如果您使用的是IntelliJ

    File -> 'Invalidate Caches/Restart'

    要么

    • 被引用的类位于另一个项目中,并且该依赖项未添加到项目的Gradle构建文件中 . 所以我添加了依赖项

    compile project(':anotherProject')

    它工作 . HTH!

  • -2

    如果您忘记 new ,您也会收到此错误:

    String s = String();
    

    String s = new String();
    
  • 19

    对于提示,请仔细查看抛出错误的类名称和行号,例如:编译失败[ERROR] \ applications \ xxxxx.java:[44,30]错误:找不到符号

    另一个原因是不支持java版本的方法说jdk7 vs 8.检查你的%JAVA_HOME%

  • 2

    如果您忘记了新内容,也可能会收到此错误:

    int i = Integer(); ---- >>应该是“ new Integer()

    (这就是为什么我在我的情况下得到错误)

  • 14

    如果你在其他地方的构建中遇到这个错误,而你的IDE说一切都很好,那么检查你在两个地方都使用相同的Java版本 .

    例如,Java 7和Java 8具有不同的API,因此在较旧的Java版本中调用不存在的API会导致此错误 .

  • 316

    1.“无法找到符号”错误是什么意思?

    首先,它是编译错误1 . 这意味着您的Java源代码中存在问题,或者您编译它的方式存在问题 .

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

    • 关键字:如 truefalseclasswhile 等 .

    • 文字:像 42'X'"Hi mum!" .

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

    • 标识符:如 ReaderitoStringprocessEquibalancedElephants 等 .

    • 评论和空白 .

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

    “无法找到符号”错误意味着编译器无法执行此操作 . 您的代码似乎是指编译器无法理解的内容 .

    2.什么可能导致“找不到符号”错误?

    作为第一个订单,只有一个原因 . 编译器查找了应该定义标识符的所有位置,并且找不到定义 . 这可能是由许多事情引起的 . 常见的如下:

    • 对于一般的标识符:

    • 也许你拼错了名字;即 StringBiulder 而不是 StringBuilder . Java不能也不会尝试弥补拼写错误或输入错误 .

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

    • 也许你不恰当地使用了下划线;即 mystringmy_string 是不同的 . (如果你遵守Java风格规则,你将在很大程度上受到这种错误的保护...)

    • 也许你正在尝试使用声明为"somewhere else"的东西;即在不同的上下文中,您隐含地告诉编译器要查看的内容 . (一个不同的类?一个不同的范围?一个不同的包?一个不同的代码库?)

    • 对于应引用变量的标识符:

    • 也许您忘了声明变量 .

    • 也许变量声明在您尝试使用它时不在范围内 . (见下面的例子)

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

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

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

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

    • 对于应该是类名的标识符:

    • 也许您忘了导入课程 .

    • 也许您使用了"star" imports,但未在导入的任何包中定义该类 .

    • 也许你忘记了 new ,如:

    String s = String();  // should be 'new String()'
    
    • 对于类型或实例似乎没有您希望它拥有的成员的情况:

    • 也许您已经声明了一个嵌套类或一个泛型参数,它会影响您要使用的类型 .

    • 也许您正在隐藏静态或实例变量 .

    • 也许你导入了错误的类型;例如由于IDE完成或自动更正 .

    • 也许您正在使用(编译)错误版本的API .

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

    问题通常是上述的组合 . 例如,也许你"star"导入 java.io.* 然后尝试使用 Files 类...这是 java.nio 而不是 java.io . 或许你打算写 File ...这是 java.io 中的一个类 .


    以下是不正确的变量范围如何导致“无法找到符号”错误的示例:

    for (int i = 0; i < strings.size(); i++) {
        if (strings.get(i).equalsIgnoreCase("fnoord")) {
            break;
        }
    }
    if (i < strings.size()) {
        ...
    }
    

    这将在 if 语句中为 i 给出"Cannot find symbol"错误 . 虽然我们之前声明了 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 循环的主体,因此 for 语句中先前的 i 声明超出了块的范围 .


    这是由拼写错误引起的“无法找到符号”错误的另一个示例 .

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

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

    在我遇到的例子中,程序员实际上已经遗漏了一个操作员 . 他打算写的是这样的:

    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 说"Cannot find symbol" . 有很多方法我可以这样做:

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

    • 我可以在内部 for 循环或外部 for 循环之前为 j 添加声明 - 可能是正确的 .

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

    • 等等 .

    关键是您需要了解代码尝试执行的操作才能找到正确的修复程序 .

    4.模糊不清的原因

    以下是一些“无法找到符号”看似莫名其妙的情况......直到你仔细观察 .

    • Incorrect dependencies :如果您使用的是管理构建路径和项目依赖关系的IDE或构建工具,那么您可能在依赖项中犯了错误;例如遗漏了一个依赖,或选择了错误的版本 . 如果您使用的是构建工具(Ant,Maven,Gradle等),请检查项目's build file. If you are using an IDE, check the project'的构建路径配置 .

    • You are not recompiling :有时新的Java程序员不会实现可重复的"build process";例如使用IDE,Ant,Maven,Gradle等 . 在这种情况下,程序员最终可能会追逐他的尾巴寻找一个虚幻的错误,这个错误实际上是由于没有正确地重新编译代码而导致的......等等......

    • An earlier build problem :早期构建可能以给出缺少类的JAR文件的方式失败 . 如果您使用构建工具,通常会注意到这样的故障 . 但是,如果您从其他人那里获取JAR文件,则依赖于它们正确构建并注意错误 . 如果您怀疑这一点,请使用 tar -tvf 列出可疑JAR文件的内容 .

    • IDE issues :人们已经报告了他们的IDE混淆的情况,IDE中的编译器找不到存在的类......或者相反的情况 .

    • 如果IDE的缓存与文件系统不同步,则会发生这种情况 . 有IDE特定的方法来解决这个问题 .

    • 这可能是一个IDE错误 . 例如,@ Joel Costigliola描述了Eclipse无法正确处理Maven "test"树的场景:see this answer .

    • Redefining system classes :我见过编译器抱怨的情况 substring 是一个未知的符号,如下所示

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

    事实证明,程序员已经创建了自己的 String 版本,并且他的类版本没有定义 substring 方法 .

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

    • Homoglyphs: 如果对源文件使用UTF-8编码,则可能具有看起来相同但实际上不同的标识符,因为它们包含同形字符 . 有关更多信息,请参见this page .

    您可以通过将自己限制为ASCII或Latin-1作为源文件编码,并将Java \uxxxx 转义限制为其他字符来避免这种情况 .


    1 - 如果,确实在运行时异常或错误消息中看到了这一点,那么您已将IDE配置为运行具有编译错误的代码,或者您的应用程序正在生成并编译代码..在运行时 .

    2 - 土木工程的三个基本原则:水不会上坡,木板侧面较强,你不能用绳子推 .

  • 8

    One more example of 'Variable is out of scope'

    因为即使它感觉不错,我也是非法的 .

    考虑以下代码:

    if(somethingIsTrue()) {
      String message = "Everything is fine";
    } else {
      String message = "We have an error";
    }
    System.out.println(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-values预先分配给外部范围中的变量名称,然后在以下情况下重新分配:

    String message = "We have an error";
    if(somethingIsTrue()) {
      message = "Everything is fine";
    } 
    System.out.println(message);
    
  • 0

    “找不到”意味着,编译器找不到合适的变量,方法,类等等...如果你得到那个错误按摩,首先你要找到代码行哪里得到错误按摩......然后你会能够在使用之前找到哪个变量,方法或类没有定义 . 确认初始化该变量后,方法或类可以用于以后的需要...考虑以下示例 .

    我将创建一个演示类并打印一个名称......

    class demo{ 
          public static void main(String a[]){
                 System.out.print(name);
          }
    }
    

    现在看结果..

    enter image description here

    那个错误说,“变量名称找不到” . 定义和初始化'name'变量的值可以废除那个错误..实际上是这样的,

    class demo{ 
          public static void main(String a[]){
    
                 String name="smith";
    
                 System.out.print(name);
          }
    }
    

    现在看看新的输出......

    enter image description here

    好的,成功地解决了这个错误 . 同时,如果你能得到“找不到方法”或“找不到类”的东西,首先,定义一个类或方法,并在使用后...

  • 0

    我也得到了这个错误 . (我用谷歌搜索,我被引导到这个页面)

    Problem: 我在另一个项目B中定义的类中调用了项目A的类中定义的静态方法 . 我收到以下错误:

    error: cannot find symbol
    

    Solution: 我通过首先构建定义方法的项目然后调用方法的项目来解决这个问题 .

  • 0

    在Eclipse中获取此错误的一种方法:

    • src/test/java 中定义一个类 A .

    • src/main/java 中定义另一个使用类 A 的类 B .

    结果:Eclipse将编译代码,但maven将给出“找不到符号” .

    基本原因:Eclipse正在使用主树和测试树的组合构建路径 . 不幸的是,它不支持为Eclipse项目的不同部分使用不同的构建路径,这是Maven所需要的 .

    方案:

    • 唐't define your dependencies that way; i.e. don' t犯了这个错误 .

    • 使用Maven定期构建代码库,以便尽早发现这个错误 . 一种方法是使用CI服务器 .

相关问题