“找不到交易品种”或“无法解析交易品种”错误是什么意思?

What does a "Cannot find symbol" or "Cannot resolve symbol" error mean?

提问人:Stephen C 提问时间:9/7/2014 最后编辑:Stephen C 更新时间:1/12/2023 访问量:1578747

问:

请解释以下关于“找不到符号”、“无法解析符号”或“找不到符号”错误(在 Java 中):

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

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

java 编译器错误 无法找到符号

评论


答:

550赞 Stephen C 9/7/2014 #1

0. 这些错误之间有什么区别吗?

没有。“找不到符号”、“无法解析符号”和“找不到符号”都表示相同的含义。(不同的 Java 编译器是由不同的人编写的,不同的人使用不同的措辞来表达同样的事情。

1. “找不到交易品种”错误是什么意思?

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

Java 源代码由以下内容组成:

  • 关键字:喜欢、等。classwhile
  • 文字:like 、 、 和 。truefalse42'X'"Hi mum!"
  • 运算符和其他非字母数字标记:如、、等。+={
  • 标识符:如 、 、 、 等。ReaderitoStringprocessEquibalancedElephants
  • 注释和空格。

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

“找不到符号”错误意味着编译器无法执行此操作。您的代码似乎引用了编译器无法理解的内容。

2. 什么会导致“找不到交易品种”错误?

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

  • 对于一般的标识符:

    • 也许你的名字拼写错误;即 而不是。Java 不能也不会尝试弥补错误的拼写或打字错误。StringBiulderStringBuilder
    • 也许你弄错了案子;即 而不是。所有 Java 标识符都区分大小写。stringBuilderStringBuilder
    • 也许你不恰当地使用了下划线;即 并且是不同的。(如果你坚持 Java 风格的规则,你将在很大程度上免受这个错误的影响......mystringmy_string
    • 也许您正在尝试使用被宣布为“其他地方”的东西;即,在与您隐式告诉编译器查看的上下文不同的上下文中。(不同的班级?不同的范围?不同的套餐?不同的代码库?
  • 对于应引用变量的标识符:

    • 也许您忘记声明变量。
    • 也许变量声明在您尝试使用它时超出了范围。(见下面的例子)
  • 对于应为方法或字段名称的标识符:

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

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

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

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

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // maybe that should be 'strings[0].charAt(3)'
      
  • 对于应为类名的标识符:

    • 也许您忘记导入类了。

    • 也许您使用了“星型”导入,但您导入的任何包中都没有定义该类。

    • 也许你忘记了:new

          String s = String();  // should be 'new String()'
      
    • 也许您正在尝试导入或以其他方式使用已在默认包中声明的类;即没有语句的类所在的那个。package

      提示:了解包。您应该只对由一个类组成的简单应用程序使用默认包...或者一口气,一个 Java 源文件。

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

    • 也许你已经声明了一个嵌套类或一个泛型参数,它隐藏了你要使用的类型。
    • 也许您正在隐藏静态变量或实例变量。
    • 也许您导入了错误的类型;例如,由于 IDE 完成或自动更正可能建议而不是 .java.awt.Listjava.util.List
    • 也许您正在使用(针对)错误版本的 API。
    • 也许您忘记将对象转换为适当的子类。
    • 也许您已将变量类型声明为具有您要查找的成员的变量的超类型。

问题通常是上述因素的组合。例如,也许您“加星”导入,然后尝试使用该类......这不是.或者也许你是想写......这是 中的一个类。java.io.*Filesjava.niojava.ioFilejava.io


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

List<String> strings = ...

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

这将在语句中给出“找不到符号”错误。虽然我们之前声明过,但该声明只在声明及其正文的范围内。语句中对 的引用看不到 的声明。它超出了范围iififoriifi

(此处的适当更正可能是将语句移到循环内,或者在循环开始之前声明。ifi


下面是一个引起困惑的例子,其中拼写错误会导致看似莫名其妙的“找不到符号”错误:

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

这将在调用中给出一个编译错误,说找不到。但是(我听到你说)我确实宣布了!printlni

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

for (int i = 0; i < 100; i++); 

// The previous and following are separate statements!!

{
    System.out.println("i is " + i);
}

块不是循环的主体,因此语句中的先前声明超出了块的范围。{ ... }forifor


这是由拼写错误导致的“找不到符号”错误的另一个示例。

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

尽管有先前的声明,但表达式中的 是错误的。编译器将查找一个名为 的方法,但找不到。前面声明的位于变量的命名空间中,而不是方法的命名空间中。tmptmp(...)tmptmp

在我遇到的例子中,程序员实际上遗漏了一个运算符。他想写的是这样的:

int res = tmp * (a + b);

如果从命令行进行编译,编译器可能找不到符号,还有另一个原因。您可能只是忘记编译或重新编译其他类。例如,如果您有类和 where 使用 .如果你从未编译过,并且运行了,你很容易发现编译器找不到符号。简单的答案是编译和一起;例如 或。或者最好还是使用 Java 构建工具;例如 Ant、Maven、Gradle 等。FooBarFooBarBarjavac Foo.javaBarFooBarjavac Foo.java Bar.javajavac *.java

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

3. 如何修复这些错误?

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

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

然后你想想你的代码应该说什么。最后,你要弄清楚你需要对源代码进行哪些更正才能做你想做的事。

请注意,并非每个“更正”都是正确的。考虑一下:

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

假设编译器对 说 “找不到符号”。我可以通过多种方式“修复”这个问题:j

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

关键是你需要了解你的代码试图做什么,以便找到正确的修复。

4.晦涩难懂的原因

以下是“找不到符号”似乎莫名其妙的几种情况......直到你仔细观察。

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

  2. 找不到符号“var”:您可能正在尝试使用较旧的编译器或较旧的级别编译使用局部变量类型推断(即声明)的源代码。它是在 Java 10 中引入的。检查 JDK 版本和生成文件,以及 IDE 设置(如果在 IDE 中出现这种情况)。var--sourcevar

  3. 您没有编译/重新编译:有时会发生这样的情况:新的 Java 程序员不了解 Java 工具链的工作原理,或者没有实现可重复的“构建过程”;例如,使用 IDE、Ant、Maven、Gradle 等。在这种情况下,程序员最终可能会追逐他的尾巴,寻找一个虚幻的错误,这个错误实际上是由于没有正确重新编译代码等造成的。

    另一个例子是当你使用 (Java 9+) 编译和运行一个类时。如果该类依赖于您尚未编译(或重新编译)的另一个类,则可能会收到引用第二个类的“无法解析符号”错误。其他源文件不会自动编译。该命令的新“编译并运行”模式不是为运行具有多个源代码文件的程序而设计的。java SomeClass.javajava

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

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

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

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

    • 这可能是一个 IDE 错误。例如,@Joel Costigliola 描述了一个 Eclipse 没有正确处理 Maven“测试”树的场景:请参阅此答案。(显然,这个特定的错误很久以前就已经修复了。

  6. Android 问题:当您为 Android 编程时,如果出现与 相关的“找不到符号”错误,请注意,符号是由文件定义的。检查您的文件是否正确且位于正确的位置,以及是否已生成/编译相应的类文件。请注意,Java 符号区分大小写,因此相应的 XML ID 也区分大小写。RRcontext.xmlcontext.xmlR

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

  7. 隐藏系统类:我见过编译器抱怨这是一个未知符号的情况,如下所示substring

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

    事实证明,程序员创建了自己的版本,而他的类版本没有定义方法。我见过人们用 和其他类来做这件事。StringsubstringSystemScanner

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

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

    java.lang.String s = ...
    java.lang.String s1 = s.substring(1);
    
  8. 同形文字:如果对源文件使用 UTF-8 编码,则标识符可能看起来相同,但实际上不同,因为它们包含同形字形。有关详细信息,请参阅此页面

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


1 - 如果碰巧在运行时异常或错误消息中看到此情况,则表示您已将 IDE 配置为运行有编译错误的代码,或者您的应用程序正在生成和编译代码。在运行时。
2 - 土木工程的三个基本原则:水不会流上山坡,木板的侧面更坚固,你不能推绳子。

评论

0赞 Jogi 5/23/2016
我还有另一种情况,当eclipse没有看到问题时发生了这个编译错误:两个类在另一个类中分别定义了依赖关系。就我而言,我有一个枚举,实现了一个接口,在一个类中定义,我愚蠢地已经使用了该枚举。
0赞 Andres Stadelmann 5/28/2016
与上面的评论有点类似,当我从 Eclipse 编译和运行我的程序时,它没有问题。从控制台编译它会引发一堆“找不到符号”错误,这些错误通常与导入中的最后一个元素有关。我不知道是什么原因导致的,因为代码中确实没有任何错误。
0赞 Pshemo 11/14/2019
另一个问题是 IDE 可能会将其他错误“解释”到此类别中。例如,如果放在标准编译器下的类级别,会给我们(演示),但在 IntelliJ 中,我们将看到(演示)。printlnSystem.out.println<identifier> expectedCannot resolve symbol 'println'
0赞 Stephen C 11/14/2019
哇。我称之为编译器错误。
0赞 Stephen C 5/9/2021
(似乎 Intellij 采用了语法上无效的内容(需要声明的语句),然后尝试解析符号。但是编译器已经足够混乱,以至于它无法解析应该解析的符号......如果语句在正确的上下文中,则会解决。这会导致误导性的编译错误消息。
35赞 thinkterry 4/17/2015 #2

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

String s = String();

String s = new String();

因为没有关键字的调用将尝试查找没有参数的(本地)方法 - 并且该方法签名可能未定义。newString

评论

3赞 hazirovich 7/16/2020
经过一个小时的扫描我的代码,我得到了这个答案——感谢上帝!
20赞 Jan 12/6/2015 #3

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

正如我已经见过几次这样的问题,也许再举一个例子来说明什么是非法的,即使它可能感觉还不错。

请考虑以下代码:

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

这是无效的代码。因为这两个命名的变量在各自的作用域之外都不可见 - 在这种情况下,这将是周围的括号。message{}

你可能会说:“但是一个名为 message 的变量是以任何一种方式定义的 - 所以 message 是在 ”.if

但你错了。

Java 没有 or 运算符,因此它必须依靠跟踪变量范围来找出变量何时不再使用(以及对这些原因变量的引用)。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);

评论

4赞 Stephen C 11/1/2017
“Java 没有 free() 或 delete 运算符,因此它必须依靠跟踪变量范围来找出变量何时不再使用(以及对这些原因变量的引用)。”- 虽然是真的,但这无关紧要。C 和 C++ 分别具有自由/删除运算符,但与您的示例等效的 C/C++ 代码将是非法的。C 和 C++ 块限制变量的范围,就像在 Java 中一样。事实上,对于大多数“块结构”语言来说都是如此。
1赞 Daniel Pryden 4/3/2018
对于在每个分支上分配不同值的代码,更好的解决方案是使用空白的最终变量声明。
5赞 Jonathan Lin 3/8/2016 #4

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

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

13赞 Joel Costigliola 5/13/2016 #5

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

  1. 在 中定义一个类。Asrc/test/java
  2. 定义另一个使用 class 的类。Bsrc/main/javaA

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

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

溶液:

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

评论

0赞 6/15/2016
这个问题的解决方案是什么?
2赞 Joel Costigliola 6/16/2016
无论你在 src/main/java 中使用什么,都需要在 src/main/java 或任何编译/运行时依赖项(而不是测试依赖项)中定义。
3赞 Divya Jose 9/28/2016 #6

我也收到这个错误。(为此,我用谷歌搜索了一下,然后我被引导到这个页面)

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

error: cannot find symbol

溶液:我通过首先构建定义方法的项目,然后构建从中调用该方法的项目来解决此问题。

评论

0赞 buildingKofi 9/13/2019
是的,例如,如果您决定将一些可重用的函数从当前包移动到通用 utils 包,但随后您忘记在从当前包调用函数之前编译通用包,则可能会发生这种情况。
0赞 Striker 9/6/2017 #7

有关提示,请仔细查看引发错误的类名名称和行号,例如: 编译失败 [错误] \应用程序\xxxxx.java:[44,30] 错误:找不到符号

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

评论

1赞 Stephen C 7/6/2018
这只是说了与其他答案所说的相同的事情。
8赞 Gayan Sampath 6/30/2018 #8

“找不到”是指,编译器找不到合适的变量、方法、类等......如果你得到了那个错误按摩,首先你要找到代码行,在哪里得到错误按摩..然后,您将能够找到在使用之前尚未定义的变量,方法或类。确认初始化变量、方法或类后,可用于以后的需要...请看以下示例。

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

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

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

5赞 avp 8/18/2018 #9

正如人们上面提到的,可能有多种情况。有几件事帮助我解决了这个问题。

  1. 如果您使用的是 IntelliJ

    File -> 'Invalidate Caches/Restart'

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

    compile project(':anotherProject')

它奏效了。呵呵!

4赞 UdayKiran Pulipati 1/24/2019 #10

如果eclipse Java构建路径映射到7,8,并且在项目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 支持 http://download.eclipse.org/eclipse/updates/4.9-P-buildsLocation:

然后在 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 构建步骤

1赞 ANIL KUMAR 8/7/2019 #11

您使用 编译了代码,用于运行它,并且它工作正常。现在,如果您更改了代码中的某些内容,然后在没有编译的情况下运行它,则会出现此错误。maven compilemaven test

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

评论

1赞 Stephen C 5/9/2021
这种解释没有意义。“找不到符号”错误是编译错误。在>>运行<<测试时不会发生这种情况。不过,它可能会在>>编译<<测试时发生。
1赞 Stephen C 5/9/2021
另外,我很困惑你设法在没有编译被测代码的情况下编译测试。除非他们出于某种原因在单独的项目中。如果你运行 ,那应该重新编译项目中的所有内容......在运行测试之前。如果运行 ,则不应重新编译任何内容。mvn testmvn surefile:test
0赞 VIPIN KUMAR 9/8/2019 #12

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

  1. 将文件从目录移动到目录 (IntelliJ IDE)context.xmlsrc/java/packageresource
  2. 清理目录。target

评论

0赞 Huy Hóm Hỉnh 10/2/2019
在不关心引用的情况下移动文件可能会导致此错误。我已经遇到过这个了。只需在 Git 上重置并小心地再次移动,错误即可解决。
0赞 user207421 12/4/2023
Context.xml 与编译错误无关。
23赞 Ajay 10/10/2019 #13

解决

使用 IntelliJ

选择 Build->Rebuild Project 将解决它

评论

8赞 Maarten Bodewes 10/20/2019
这很大程度上取决于,通常不会。
1赞 coder3 4/5/2021
这对我有用。我无法弄清楚,因为软件包/目录都是正确的。似乎需要重建以合并更改。
0赞 sakra 7/20/2020 #14

我们在设置为 Gradle 多项目构建的 Java 项目中收到错误。事实证明,其中一个子项目缺少 Gradle Java 库插件。 这样可以防止子项目的类文件对生成中的其他项目可见。

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

plugins {
    ...
    id 'java-library'
}
-5赞 Felipe Franco 11/20/2020 #15

Enter image description here

我像这样解决了这个错误......Android的疯狂。我将软件包名称设置为“适配器”,然后使用“a”而不是“A”将名称重构为适配器并解决了错误。

评论

3赞 Stephen C 11/20/2020
这不是 Android 特有的,也不是疯狂的。Java 标识符区分大小写。并且类名/包名的大小写应与相应的源文件、目录和 .class 文件的大小写相匹配。如果你搞砸了这个,那么工具链很可能找不到相关文件。
0赞 Felipe Franco 11/20/2020
感谢您的澄清 Stephen C
0赞 Adrian C 1/12/2022 #16

回复:4.4:Stephen C 的出色回答中的早期构建问题:

我在开发OSGi应用程序时遇到了这种情况。 我有一个 Java 项目,它是 的依赖项。 构建时,出现错误:ABB

Compilation failure: org.company.projectA.bar.xyz does not exist

但是在Eclipse中,根本没有任何编译问题。

调查

当我查看时,有 的类,但没有 的类。A.jarorg.company.projectA.foo.abcorg.company.projectA.bar.xyz

缺少类的原因是,在 中,有一个用于导出相关包的条目。A/pom.xml

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    ...
    <configuration>
        <instructions>
            ....
            <Export-Package>org.company.projectA.foo.*</Export-Package>
        </instructions>
    </configuration>
</plugin>

溶液

添加缺少的包,如下所示:

<Export-Package>org.company.projectA.foo.*,org.company.projectA.bar.*</Export-Package>

并重建一切。

现在,它包含了所有预期的类,并且所有内容都编译了。A.jar

0赞 LOrD_ARaGOrN 8/1/2022 #17

我收到以下错误

java: cannot find symbol
  symbol: class __

为了解决这个问题,我尝试启用龙目岛,重新启动IntelliJ IDEA等,但以下方法对我有用。

IntelliJ IDEA → 选项 → 编译器共享构建进程 VM 选项,并将其设置为

-Djps.track.ap.dependencies=false

然后运行

mvn clean install
-1赞 jumping_monkey 10/5/2022 #18

可选.isEmpty()

我很高兴在我的 IDE 中使用,它工作正常,因为我正在使用 >= 编译/运行我的项目。现在,当我在命令行上使用 Gradle(在 JDK 8 上运行)时,我在编译任务中遇到了令人讨厌的错误。!Optional.isEmpty()JDK11

为什么?

从文档中(注意最后一行):

boolean java.util.Optional.isEmpty()

If a value is not present, returns true, otherwise false.
Returns:true if a value is not present, otherwise false
Since:11