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

时间:2014-09-07 01:12:09

标签: java compiler-errors cannot-find-symbol

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

  • 这个错误是什么意思?
  • 什么东西会导致这个错误?
  • 程序员如何解决此错误?

此问题旨在成为关于Java中“无法找到符号”编译错误的综合问题。

17 个答案:

答案 0 :(得分:356)

1。什么是"找不到符号"错误意味着什么?

首先,它是编译错误 1 。这意味着要么在您的Java源代码中存在问题,在编译它的方式上存在问题。

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

  • 关键字:例如truefalseclasswhile等。
  • 文字:例如42'X'以及"Hi mum!"
  • 运算符和其他非字母数字标记:例如+={等。
  • 标识符:例如ReaderitoStringprocessEquibalancedElephants等。
  • 评论和空白。

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

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

2。什么可能导致"无法找到符号"错误?

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

  • 通常用于标识符:
    • 也许你拼错了这个名字;即StringBiulder而不是StringBuilder。 Java不能也不会试图弥补拼写错误或输入错误。
    • 也许你弄错了;即stringBuilder而不是StringBuilder。所有Java标识符都区分大小写。
    • 也许您不恰当地使用了下划线;即mystringmy_string不同。 (如果你坚持Java风格规则,你将在很大程度上受到这种错误的保护......)
    • 也许你正在尝试使用已声明的东西"其他地方&#34 ;;即在不同的上下文中,您隐含地告诉编译器。 (一个不同的类?一个不同的范围?一个不同的包?一个不同的代码库?)
  • 对于应引用变量的标识符:
    • 也许您忘了申报变量。
    • 也许变量声明在您尝试使用它时超出了范围。 (见下面的例子)
  • 对于应该是方法或字段名称的标识符:
    • 也许您正在尝试引用未在父/祖先类或接口中声明的继承方法或字段。
    • 也许您正在尝试引用您正在使用的类型中不存在的方法或字段(即尚未声明);例如"someString".push() 2
    • 也许您正在尝试将方法用作字段,反之亦然;例如"someString".lengthsomeArray.length()
  • 对于应该是类名的标识符:

    • 也许您忘了导入课程。
    • 也许你曾经使用过" star"导入,但在您导入的任何包中都没有定义类。
    • 也许您忘记了new,如:

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

    • 也许您已经声明了一个嵌套类或一个通用参数 shadows 您要使用的类型。
    • 也许您正在隐藏静态或实例变量。
    • 也许你导入了错误的类型;例如由于IDE完成或自动更正。
    • 也许您正在使用(编译)错误版本的API。
    • 也许您忘了将对象转换为适当的子类。

问题通常是上述的组合。例如,也许你"明星"已导入java.io.*,然后尝试使用Files而非java.nio的{​​{1}}类...或许你打算写java.io ... File中的一个类。


以下是一个示例,说明不正确的变量范围如何导致"找不到符号"错误:

java.io

这将给出一个&#34;找不到符号&#34; for (int i = 0; i < strings.size(); i++) { if (strings.get(i).equalsIgnoreCase("fnoord")) { break; } } if (i < strings.size()) { ... } 语句中i的错误。虽然我们之前声明了if,但该声明只是i语句及其正文的范围for语句中对i的引用无法查看 if的声明。 超出范围

(这里适当的修正可能是在循环中移动i语句,或在循环开始之前声明if。)


这是一个导致困惑的例子,其中拼写错误导致看似无法解释的错误&#34;找不到符号&#34;错误:

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的先前声明超出范围< / em>在街区。


这是另一个&#34;无法找到符号&#34;由错字引起的错误。

for

尽管有上一个声明,但int tmp = ... int res = tmp(a + b); 表达式中的tmp是错误的。编译器将查找名为tmp(...)的方法,但不会找到一个方法。先前声明的tmp位于变量的名称空间中,而不是方法的名称空间。

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

tmp

如果从命令行编译,编译器可能找不到符号还有另一个原因。您可能只是忘记编译或重新编译其他类。例如,如果您有int res = tmp * (a + b); Foo,其中Bar使用Foo。如果您从未编译过Bar而运行Bar,则可能会发现编译器无法找到符号javac Foo.java。简单的答案是将BarFoo汇总在一起;例如Barjavac Foo.java Bar.java。或者更好的是仍然使用Java构建工具;例如Ant,Maven,Gradle等。

还有一些其他更为模糊的原因......我将在下面讨论。

3。我该如何解决这些错误?

一般来说,您首先要弄清楚导致编译错误。

  • 查看编译错误消息指示的文件中的行。
  • 确定错误消息正在讨论的符号。
  • 弄清楚为什么编译器说它无法找到符号;见上文!

然后你想想你的代码应该说些什么。最后,您需要确定需要对源代码进行哪些更正才能完成所需的操作。

请注意,并非所有&#34;更正&#34;是正确的。考虑一下:

javac *.java

假设编译器说&#34;找不到符号&#34;为for (int i = 1; i < 10; i++) { for (j = 1; j < 10; j++) { ... } } 。我有很多方法可以修复&#34;的是:

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

关键是你需要来了解你的代码尝试做什么才能找到正确的解决方案。

4。模糊原因

以下是一些&#34;无法找到符号&#34;看起来似乎莫名其妙......直到你仔细观察。

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

  2. 您没有重新编译:有时新的Java程序员不了解Java工具链是如何工作的,或者没有实现可重复的#34 ;构建过程&#34 ;;例如使用IDE,Ant,Maven,Gradle等。在这种情况下,程序员最终可能会追逐他的尾巴寻找由于未正确重新编译代码而导致实际的虚幻错误等...

  3. 较早的构建问题:早期构建可能会导致JAR文件缺少类。如果您使用构建工具,通常会注意到这种失败。但是,如果您从其他人那里获取JAR文件,则依赖于他们正确构建,并注意到错误。如果您怀疑这一点,请使用for列出可疑JAR文件的内容。

  4. IDE问题:人们已经报告了他们的IDE混淆并且IDE中的编译器找不到存在的类的情况......或者相反的情况。

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

    • 这可能是一个IDE错误。例如@Joel Costigliola描述了Eclipse不处理Maven&#34;测试&#34;树正确:see this answer

  5. 重新定义系统类:我见过编译器抱怨tar -tvf是一个未知符号的情况,如下所示

    substring

    事实证明,程序员已经创建了自己的String s = ... String s1 = s.substring(1); 版本,并且他的版本没有定义String方法。

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

  6. Homoglyphs:如果您对源文件使用UTF-8编码,则可能使看起来的标识符相同,但实际上是不同的因为它们包含同形体。有关详细信息,请参阅this page

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


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

    2 - 土木工程的三个基本原则:水不会上坡,木板侧面更强,而且你不能推上一根绳子

答案 1 :(得分:21)

如果忘记new

,您也会收到此错误消息
String s = String();

String s = new String();

答案 2 :(得分:14)

“变量超出范围”的另一个例子

正如我已经看过几次这样的问题,也许还有一个例子就是非法的,即使它可能感觉没问题。

考虑以下代码:

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

“哦,有重复的代码,让我们拉出那条普通的线路” - &gt;它就在那里。

处理这种范围问题的最常见方法是将else-values预先分配给外部范围中的变量名称,然后在以下情况下重新分配:

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

答案 3 :(得分:8)

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

  1. A
  2. 中定义课程src/test/java
  3. B中定义另一个使用班级src/main/java的班级A
  4. 结果:Eclipse将编译代码,但是maven将给出&#34;找不到符号&#34;。

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

    解决方案:

    1. 不要那样定义你的依赖关系;即不要犯这个错误。
    2. 使用Maven定期构建代码库,以便尽早发现这个错误。一种方法是使用CI服务器。

答案 4 :(得分:3)

“找不到”表示编译器找不到合适的变量,方法,类等...如果您得到了错误提示,首先您要查找获得错误提示的代码行。那么在使用它之前,您将能够找到尚未定义的变量,方法或类。在确认初始化后,该变量,方法或类可用于以后的需求...请考虑以下示例。

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

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

现在看看结果。

enter image description here

该错误表示“找不到变量名”。可以取消定义和初始化“名称”变量的值。实际上就是这样,

class demo{ 
      public static void main(String a[]){

             String name="smith";

             System.out.print(name);
      }
}

现在看看新的输出...

enter image description here

好,成功解决了这个错误。.同时,如果您得到“找不到方法”或“找不到类”的东西,请首先定义一个类或方法,然后再使用它。 >

答案 5 :(得分:2)

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

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

答案 6 :(得分:1)

如果将eclipse Java构建路径映射到7、8,并且在Project pom.xml Maven属性java.version中提到Java版本高于(9、10、11等。),则需要更新7,8在pom.xml文件中。

在Eclipse中,如果Java映射到Java版本11,在pom.xml中,它映射到Java版本8,请通过在Eclipse IDE中执行以下步骤来将Eclipse支持更新为Java 11。 帮助->安装新软件->

将链接http://download.eclipse.org/eclipse/updates/4.9-P-builds粘贴到 使用

添加(将打开弹出窗口)->

Name: Java 11支持 Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

然后如下所述更新 pom.xml 文件的Maven属性中的Java版本

<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

最后,右键单击项目Debug as-> Maven clean,Maven构建步骤

答案 7 :(得分:1)

您使用maven compile编译了代码,然后使用maven测试运行了它。现在,如果您更改了代码中的某些内容,然后又不进行编译就运行它,则会收到此错误。

解决方案:再次编译它,然后运行测试。对我来说,它是这样工作的。

答案 8 :(得分:1)

就我而言-我必须执行以下操作:

  1. context.xml文件从src/java/package移动到resource目录(IntelliJ IDE)
  2. 清理target目录。

答案 9 :(得分:1)

已解决

选择构建-> 重建项目即可解决

答案 10 :(得分:0)

人们可能会提到各种情况。有几件事帮助我解决了这个问题。

  1. 如果您使用的是IntelliJ

    File -> 'Invalidate Caches/Restart'

OR

  1. 被引用的类在另一个项目中,并且该依赖项未添加到我项目的Gradle构建文件中。所以我使用

    添加了依赖项

    compile project(':anotherProject')

成功了。 HTH!

答案 11 :(得分:0)

enter image description here

我这样解决了这个错误... android的疯狂。我将程序包名称命名为Adapter,然后将名称重构为使用“ a”而不是“ A”的适配器,并解决了错误。

答案 12 :(得分:0)

我们在设置为Gradle多项目构建的Java项目中遇到了错误。原来,其中一个子项目缺少Gradle Java Library plugin。 这样可以防止子项目的类文件对构建中的其他项目可见。

按照以下方式将Java库插件添加到子项目的build.gradle后,错误消失了:

plugins {
    ...
    id 'java-library'
}

答案 13 :(得分:0)

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

另一个原因是java版本的不支持的方法,例如jdk7 vs 8。 检查你的%JAVA_HOME%

答案 14 :(得分:0)

我也遇到了这个错误。 (我用Google搜索,我被引导到此页面)

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

error: cannot find symbol

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

答案 15 :(得分:-1)

它们是什么意思?

这三个语句的含义相同:“找不到符号”、“无法解析符号”和“找不到符号”。

现在,错误的意思是编译器无法理解定义符号的引用。或者干脆编译器做不到这一点。

原因和如何修复

如果您在其他地方的构建中遇到此错误,而您的 IDE 表示一切正常,请检查您在两个地方使用的 Java 版本是否相同。 如果您在其他地方的构建中遇到此错误,并且您的 IDE 说一切正常,请检查两个地方是否使用相同的 Java 版本。

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

答案 16 :(得分:-1)

在将类文件导入我的新 Eclipse 项目(包括主类文件)后,我收到此错误。经过反复试验,我通过将导致此错误的类文件移动到我的 src 文件夹并将我的运行配置设置为我的主类的确切名称来修复它。