“找不到符号”或“无法解析符号”错误是什么意思?

2024-04-28

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

  • 他们的意思是什么?
  • 哪些因素会导致它们?
  • 程序员如何修复它们?

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


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

并不真地。 “找不到符号”、“无法解析符号”和“找不到符号”都意味着同一件事。 (不同的Java编译器是由不同的人编写的,不同的人用不同的措辞来表达同样的事情。)

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

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 源代码包含以下内容:

  • 关键词:喜欢class, while, 等等。
  • 字面意思:像true, false, 42, 'X' and "Hi mum!".
  • 运算符和其他非字母数字标记:例如+, =, {, 等等。
  • 标识符:像Reader, i, toString, processEquibalancedElephants, 等等。
  • 注释和空白。

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

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

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

作为第一顺序,只有一个原因。编译器查看了标识符所在的所有位置should被定义,但找不到定义。这可能是由多种原因造成的。常见的有以下几种:

  • 对于一般标识符:

    • 也许你的名字拼写错误; IE。StringBiulder代替StringBuilder。 Java 不能也不会尝试弥补错误的拼写或打字错误。
    • 也许你搞错了; IE。stringBuilder代替StringBuilder。所有 Java 标识符都区分大小写。
    • 也许您使用下划线的方式不恰当; IE。mystring and my_string是不同的。 (如果你坚持 Java 风格规则,你将在很大程度上避免这个错误......)
    • 也许您正在尝试使用“在其他地方”声明的东西;即在与您隐式告诉编译器查看的上下文不同的上下文中。 (不同的类?不同的范围?不同的包?不同的代码库?)
  • 对于应该引用变量的标识符:

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

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

    • 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".length or someArray.length().

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

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

    • 也许您忘记导入该类。

    • 也许您使用了“星号”导入,但该类未在您导入的任何包中定义。

    • 也许你忘记了一个new as in:

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

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

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

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

问题通常是上述问题的组合。例如,也许您“明星”导入java.io.*然后尝试使用Files类...是在java.nio not java.io。或者也许你想写File... 哪个is一个班级在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 in the if陈述。虽然我们之前声明过i,该声明只是in scope为了for声明及其正文。参考i in the 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);
}

The { ... }块不是主体for循环,因此之前的声明i in the for声明是超出范围在街区里。


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

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

尽管有先前的声明,tmp in the tmp(...)的表达是错误的。编译器会寻找一个名为的方法tmp,并且找不到。之前宣布的tmp位于变量的命名空间中,而不是方法的命名空间中。

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

int res = tmp * (a + b);

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

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

3. 如何修复这些错误?

一般来说,你首先要弄清楚什么caused编译错误。

  • 查看文件中由编译错误消息指示的行。
  • 确定错误消息所谈论的是哪个符号。
  • 弄清楚why编译器说它找不到该符号;往上看!

然后你think关于你的代码应该说的内容。最后,您确定需要对源代码进行哪些修正才能完成您想要的操作。

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

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

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

  • 我可以改变内心for to for (int j = 1; j < 10; j++)- 可能是正确的。
  • 我可以添加一个声明j before内在的for循环,或外层for循环 - 可能是正确的。
  • 我可以改变j to i在内部for循环 - 可能是错误的!
  • 等等。

重点是你need了解您的代码正在尝试做什么,以便找到正确的修复方法。

4. 不明原因

在以下几个案例中,“找不到符号”似乎令人费解……直到您仔细观察。

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

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

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

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

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

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

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

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

    • 这可能是 IDE 错误。例如,@Joel Costigliola 描述了 Eclipse 无法正确处理 Maven“测试”树的场景:看到这个答案 https://stackoverflow.com/a/37207223/139985。 (显然这个特定的错误很久以前就被修复了。)

  6. 安卓问题:当您为 Android 编程时,您遇到与以下内容相关的“找不到符号”错误:R,请注意R符号由以下定义context.xml文件。检查您的context.xml文件正确并且位于正确的位置,并且相应的R类文件已生成/编译。请注意,Java 符号区分大小写,因此相应的 XML id 也区分大小写。

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

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

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

    事实证明,程序员创建了自己的版本String并且他的课程版本没有定义substring方法。我见过人们这样做System, Scanner和其他课程。

    Lesson:不要定义与公共库类同名的自己的类!

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

    java.lang.String s = ...
    java.lang.String s1 = s.substring(1);
    
  8. 同形字:如果您对源文件使用 UTF-8 编码,则可能具有以下标识符:look相同,但实际上不同,因为它们包含同形文字。看这一页 http://en.wikipedia.org/wiki/Homoglyph了解更多信息。

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


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.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“找不到符号”或“无法解析符号”错误是什么意思? 的相关文章

  • 如何使用 Java 将 HTML 内容转换为 PDF 而不丢失格式?

    我有一些 HTML 内容 包括格式化标签 例如strong 图像等 在我的 Java 代码中 我想将此 HTML 内容转换为 PDF 文档 而不丢失 HTML 格式 有没有办法用 Java 来实现 使用 iText 或任何其他库 I use
  • 如何降低圈复杂度?

    我正在开发一个将 RequestDTO 发送到 Web 服务的类 我需要在发送请求之前验证该请求 请求可以从 3 个不同的地方发送 并且每个 请求类型 有不同的验证规则 例如请求1必须有姓名和电话号码 请求2必须有地址等 我有一个 DTO
  • java中队列的实现

    在 Java 中实现队列是一个非常常见的面试问题 我在网上冲浪 看到了许多实现 他们做了一些奇特的事情 比如实现队列接口和编写自己的addLast and removeFirst 方法 我的问题是我不能使用LinkedList 类并使用其预
  • Maven 目标的默认阶段?

    据我了解 在 Maven 中 插件目标可以附加到生命周期阶段 如果没有定义 默认阶段是什么 根据我的经验 这取决于插件的目标 例如 组装 单个 http maven apache org plugins maven assembly plu
  • JAX-WS:有状态 WS 在独立进程中失败

    我在 Tomcat 上部署了一个有状态的 Web 服务 它由工厂服务和主要 API 服务组成 并且工作得很好 工厂服务将 W3CEndpointReference 返回到主 API 实例 客户端使用会话 现在 我尝试将相同的服务作为独立应用
  • FFmpeg 不适用于 android 10,直接进入 onFailure(String message) 并显示空消息

    我在我的一个项目中使用 FFmpeg 进行视频压缩 在 Android 10 Google Pixel 3a 上 对于发送执行的任何命令 它会直接进入 onFailure String message 并显示空消息 所以我在我的应用程序 g
  • 如何屏蔽 Protobuf 中的某些字段

    我找不到一种方法来屏蔽 protobuf 结构中的某些字段 我确实阅读了有关 FieldMaskUtil 的内容并尝试了几个示例 但它似乎做了相反的操作 即复制 FieldMask 中提到的字段 这与我想要的不同 这是示例结构和相应的测试代
  • 如何使用 BufferedReader 对象从 Java 中的一行读取多个整数值?

    我正在使用 BufferedReader 类读取 Java 程序中的输入 我想读取用户的输入 该用户可以在带空格的单行中输入多个整数数据 我想读取整数数组中的所有这些数据 输入格式 用户首先输入他 她想要输入的数字数量 然后在下一行中使用多
  • 中间件 API 的最佳实践是什么? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们正在开发一个中间件 SDK 采用 C 和 Java 语言 供游戏开发人员 动画软件开发人员 阿凡达开
  • MessageDigest MD5 算法未返回我期望的结果

    我脑后的某个东西告诉我 我在这里遗漏了一些明显的东西 我正在将现有的 java 项目与第三方 api 集成 该第三方 api 使用 api 密钥的 md5 哈希进行身份验证 它对我不起作用 在调试过程中我意识到我生成的哈希值与他们提供的示例
  • 如何将txt文件添加到你的android项目中? [复制]

    这个问题在这里已经有答案了 我的Android studio版本是1 5 1 显然这个 never 版本没有 txt 文件的 asset 文件夹 您打算如何将这些文件包含到您的项目中 以及如何进一步使用您内部的应用程序 谢谢你的建议 Pro
  • 更改 RowLayout SWT Java 中元素的顺序

    有没有办法更改在行布局中创建的元素的顺序 我想将其显示在元素中 首先显示 例如 如果我创建 element1 则 element2 element3 element4 我想看到的布局为 元素4 元素3 元素2 元素1 这意味着最后创建的元素
  • setKeyListener 将覆盖 setInputType 并更改键盘

    大家好 我在两个设备之间遇到问题 在实践中使用InputType和KeyListener我正在操纵一个EditText让它从数字键盘接收逗号和数字 有关更多背景信息 请检查我之前的question https stackoverflow c
  • 在方法内声明类 - Final 关键字 [重复]

    这个问题在这里已经有答案了 给定方法中的以下内部类 IsSomething public class InnerMethod private int x public class Something private int y public
  • 使用 Cucumber Scenario Outline 处理 Excel 电子表格

    如果可能的话 我试图找到一种更优雅的方法来处理从与 Excel 电子表格行 第 n 个 相关的 Cucumber Scenario Outline 中调用第 n 个数字 目前 我正在使用迭代编号来定义要从中提取数据的 Excel 电子表格的
  • Java 8根据Map属性过滤Map对象列表以删除一些重复项

    Have a List
  • 设计抽象类时是否应该考虑序列化问题?

    一般来说这个问题来自Eclipse建议在抽象类上添加串行版本UID 由于该类是抽象类 因此该类的实例永远不会存在 因此它们永远不会被序列化 只有派生类才会被序列化 所以我的问题是放置一个安全 SuppressWarnings serial
  • 无法在 BlackBerry Playbook 上设置音量

    我在更改黑莓游戏书的音量时遇到问题 首先 我将 Android 应用程序重新打包到 Palybook 应用程序 我需要使用搜索栏更改黑莓剧本的音量 并在搜索监听器中设置音频管理器音量 这是代码 audioManager AudioManag
  • java数据结构模拟数据树

    我需要帮助定义使用什么方法 我有一个 SOAP 响应 给我一个 xml 文件 我需要在屏幕上显示 3 个相关列表 当您在第一个列表中选择一个项目时 相应的选择将出现在第二个列表中 依此类推 我只对从 xml 流中提取数据后如何有效地组织数据
  • 当我在 Java 中输入 IP 时无法连接到我的服务器

    好的 我正在尝试学习 Java 客户端 服务器的内容 并且正在浏览教程代码 如下所示 当我将 localhost 更改为我的 IP 时 它会停止工作 请帮忙 编辑 127 0 0 1 似乎也可以工作 但不是我的真实IP Copyright

随机推荐