关于Java:”找不到符号”Cannot find symbol编译错误意味着什么? | 码农家园
请解释以下'找不到符号'错误:
- 这个错误是什么意思?
- 什么事情会导致这个错误?
- 程序员如何解决这个错误?
这个问题被设计成一个关于Java中'找不到符号'编译错误的综合问题。
1。'找不到符号'错误是什么意思?
首先,它是一个编译错误1。这意味着Java源代码中存在问题,或者编译过程中存在问题。好的。
您的Java源代码包括以下内容:好的。
- 关键词:如true、false、class、while等。
- 文字:如42和'X'和'Hi mum!'。
- 运算符和其他非字母数字标记:如+、=、{等。
- 标识符:如Reader、i、toString、processEquibalancedElephants等。
- 注释和空白。
'找不到符号'错误是关于标识符的。编译代码时,编译器需要计算出代码中每个标识符的含义。好的。
'找不到符号'错误表示编译器无法执行此操作。您的代码似乎引用了编译器无法理解的内容。好的。2。什么会导致'找不到符号'错误?
作为一级命令,只有一个原因。编译器查找了所有应该定义标识符的地方,但找不到定义。这可能是由一些事情引起的。常见的有:好的。
- 对于一般标识符:
- 也许你把名字拼错了,即用StringBiulder代替StringBuilder。Java不能也不会试图补偿拼写错误或键入错误。
- 也许你搞错了,也就是说,用StringBuilder代替StringBuilder。所有Java标识符都区分大小写。
- 也许您不恰当地使用下划线;例如,mystring和my_string是不同的。(如果你坚持Java风格的规则,你将在很大程度上避免这种错误……)
- 也许您正试图使用声明为'其他地方'的内容;即,在另一个上下文中,您隐式地告诉编译器要查看的内容。(不同的班级?不同的范围?一个不同的包裹?不同的代码库?)
- 对于应引用变量的标识符:
- 也许你忘了声明变量。
- 在您试图使用变量声明时,它可能超出了范围。(见下例)
- 对于应该是方法名或字段名的标识符:
- 可能您正试图引用一个继承的方法或字段,而该方法或字段没有在父类/祖先类或接口中声明。
- 可能您试图引用的方法或字段在您使用的类型中不存在(即尚未声明);例如,'someString'.push()2。
- 也许您试图将方法用作字段,或者相反;例如,'someString'.length或someArray.length()。
对于应为类名的标识符:好的。
- 也许你忘了导入类。
- 也许您使用了'star'导入,但是类没有在您导入的任何包中定义。
也许你忘记了一个new,比如:好的。
对于类型或实例似乎没有预期的成员的情况:好的。
- 也许您已经声明了一个嵌套类或一个通用参数,它隐藏了您要使用的类型。
- 可能您正在隐藏静态或实例变量。
- 可能您导入了错误的类型;例如,由于IDE完成或自动更正。
- 也许您使用(编译)了错误的API版本。
- 也许您忘记了将对象强制转换为适当的子类。
问题往往是上述两者的结合。例如,也许你'星'进口了java.io.*,然后尝试使用Files类……在java.nio中,而不是java.io中。或者你是想写一本书。它是java.io中的一个类。好的。
下面是一个示例,说明不正确的变量范围会导致'找不到符号'错误:好的。
1
2 3 4 5 6 7 8 |
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase('fnoord')) { break; } } if (i < strings.size()) { ... } |
这将给if语句中的i带来'找不到符号'错误。虽然我们以前声明过i,但该声明仅适用于for声明及其正文。if号声明中提及的i不能看到i号声明。超出范围。好的。
(这里适当的修正可能是在循环内部移动if语句,或者在循环开始之前声明i。)好的。
下面是一个导致困惑的例子,打字错误导致了一个看似无法解释的'找不到符号'错误:好的。
1
2 3 |
这会在println调用中给您一个编译错误,说明找不到i。但(我听到你说)我确实宣布了!好的。
问题是,在{之前的分号(;)。Java语言语法将上下文中的分号定义为空语句。然后,空语句成为for循环的主体。所以代码实际上意味着:好的。
1
2 3 4 5 6 7 |
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!! { |
{ ... }块不是for循环的主体,因此for语句中以前的i声明超出了该块的范围。好的。
这里是另一个由打字错误引起的'找不到符号'错误的例子。好的。
1
2 |
int tmp = ...
int res = tmp(a + b); |
尽管之前有声明,但tmp(...)表达式中的tmp是错误的。编译器将查找名为tmp的方法,但找不到。前面声明的tmp位于变量的命名空间中,而不是方法的命名空间。好的。
在我遇到的例子中,程序员实际上漏掉了一个操作员。他想写的是:好的。
1
|
int res = tmp * (a + b);
|
如果从命令行编译,编译器可能找不到符号还有另一个原因。您可能只是忘记了编译或重新编译其他类。例如,如果您有Foo和Bar类,其中Foo使用Bar。如果您从未编译过Bar,并且运行javac Foo.java,您可能会发现编译器找不到符号Bar。简单的答案是将Foo和Bar一起编译;例如javac Foo.java Bar.java或javac *.java。或者更好地使用Java构建工具,例如Ant、Maven、Gradle等等。好的。
还有其他一些更为隐晦的原因…我将在下面处理。好的。三。如何修复这些错误?
一般来说,首先要弄清楚是什么导致了编译错误。好的。
- 查看编译错误消息指示的文件中的行。
- 确定错误消息所指的符号。
- 找出编译器为什么说找不到符号;请参见上面的内容!
然后你想想你的代码应该说什么。最后,您需要对源代码进行什么样的修正,才能完成您想要的工作。好的。
请注意,并非每个'更正'都是正确的。考虑一下:好的。
1
2 3 4 5 |
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) { ... } } |
假设编译器对j说'找不到符号'。我有很多方法可以'修复'它:好的。
- 我可以把里面的for改成for (int j = 1; j < 10; j++),也许是对的。
- 我可以在内部for循环或外部for循环之前为j添加声明-可能是正确的。
- 我可以把j改为i,在内部的for循环中-可能是错的!
- 等等。
要点是,您需要了解代码试图做什么,以便找到正确的修复方法。好的。4。模糊原因
这里有两种情况,'找不到符号'似乎难以解释…直到你看得更近。好的。
不正确的依赖项:如果使用的是管理生成路径和项目依赖项的IDE或生成工具,则可能对依赖项犯了错误;例如,遗漏了依赖项或选择了错误的版本。如果您使用的是构建工具(Ant、Maven、Gradle等),请检查项目的构建文件。如果使用的是IDE,请检查项目的构建路径配置。好的。
您没有重新编译:有时新Java程序员不理解Java工具链是如何工作的,或者没有实现可重复的'构建过程';例如使用IDE、ANT、Maven、Gradle等。在这种情况下,程序员最终可能会追寻自己的尾巴,寻找一个实际上是由于没有正确地重新编译代码而导致的错误,等等……好的。
早期版本的问题:它是可能的,早期的失败是生成在一个JAR文件单给A一班。搜索设备失效会注意到如果你是使用一个版本的工具。但是如果你从别人得到的JAR文件,你在他们的建筑,没有依赖性,和noticing错误。如果你看看这个列表的内容,使用tar -tvfof the suspect的JAR文件。
IDE的问题:有人会在他们的案例被混淆的IDE和编译器在IDE无法找到一个一流的存在……或反向的情况。
这可以发生,如果IDE’s get走出同步缓存文件系统。有特异的方式来固定这是IDE。
这可能是在IDE的bug。例如:'在目前情况costigliola乔尔Eclipse不手柄a Maven的'测试'这个正确答案:湖树。
redefining系统类:我的湖泊。在编译substring投诉,是未知的,什么样的图标
它使程序员创造出这样一个自己的版本的版本,他的String这类不substringdefine a的方法。
教训:不要使用你自己的类相同的名称作为一个类的公共图书馆。
homoglyphs:如果你使用UTF-8编码的源文件,它是可能的,有标识看起来一样,但实际上他们是不同的,因为homoglyphs包含。湖本页的更多信息。
你可以通过自己来避免这restricting ASCII或为Latin-1编码使用Java源文件,和其他\uxxxx转义字符。
1如果你perchance湖,这一运行时异常或错误消息,那么你已经配置您的IDE运行代码和编译错误,或是生成和编译代码的应用程序。在运行时。
2土木工程的基本原则三:水不流完成,A板是在其侧更强,你不能推一弦。
好的。
- 我遇到了另一种情况,在Eclipse没有看到问题的时候发生了这个编译错误:在另一个类中分别定义了两个具有依赖关系的类。在我的例子中,我有一个枚举,它实现了一个接口,这个接口是在一个类中定义的,在这个类中我愚蠢地使用了枚举。
- 有点类似于上面的注释,当我从Eclipse编译和运行程序时,它没有问题。从控制台编译它会引发一系列'找不到符号'错误,这些错误通常与导入中的最后一个元素相关。我不知道是什么导致了这一点,因为代码中没有真正的错误。
- 新到Java的人有时会将数组类型与它们的组件类型混合在一起,例如EDCOX1(0)。
如果您忘记了new,也会得到这个错误:
对战
'变量超出范围'的另一个示例
正如我已经看到过几次这样的问题,也许还有一个例子可以说明什么是非法的,即使它可能感觉良好。
考虑此代码:
1
2 3 4 5 6 |
这是无效代码。因为两个名为message的变量都不在各自的作用域之外可见,在本例中,这两个变量都是包围括号{}。
您可能会说:'但是名为message的变量是以任何方式定义的,因此message是在if之后定义的。'
但你错了。
Java没有EDCOX1,4或EDCOX1,5个操作符,因此必须依靠跟踪变量范围来发现变量何时不再被使用(连同这些变量的原因的引用)。
如果你认为你做了好事,那就更糟了。我在这样的'优化'代码之后看到了这种错误:
1
2 3 4 5 6 7 |
'哦,这里有重复的代码,让我们把这条公用线拉出来'->然后就到了。
处理此类范围问题的最常见方法是将else值预先分配给外部范围中的变量名,然后在if:
1
2 3 4 5 |
- 'Java没有For(或)删除操作符,因此它必须依赖于跟踪变量范围来找出何时不再使用变量(以及引用这些变量的原因)'-虽然是真的,但这并不相关。C和C++分别有Field/Delphi运算符,但与实例相同的C/C++代码将是非法的。C和C++块限制变量的范围,就像Java一样。事实上,大多数'块结构'语言都是如此。
- 对于在每个分支上分配不同值的代码,更好的解决方案是使用空白的final变量声明。
在Eclipse中获取此错误的一种方法:
结果:Eclipse将编译代码,但Maven将给出'找不到符号'。
根本原因:Eclipse使用的是主树和测试树的组合构建路径。不幸的是,它不支持为Eclipse项目的不同部分使用不同的构建路径,这正是Maven所要求的。
解决方案:
- 解决这个问题的方法是什么?
- 无论您在SRC/Ma/Java中使用什么,都需要在SRC/Me/Java中定义,或者以任何编译/运行时依赖关系(不是测试依赖关系)来定义。
'找不到'是指编译器找不到合适的变量、方法、类等。如果你得到了错误消息,首先你要找到代码行,在那里得到错误消息。然后你就可以在使用之前找到没有定义的变量、方法或类。确认后,初始化该变量、方法或类。可用于以后的需求…请考虑以下示例。
我将创建一个演示类并打印一个名称…
现在看看结果……
该错误表示,'变量名找不到'…定义和初始化'名称'变量的值可以取消该错误..实际上是这样的,
1
2 3 4 5 6 7 8 |
现在看看新的输出…
OK成功地解决了这个错误..同时,如果你能得到'找不到方法'或'找不到类'的东西,首先定义一个类或方法,然后使用它..
如果你在其他地方构建了这个错误,而你的IDE说一切都很好,那么检查你在两个地方使用的是相同的Java版本。
例如,Java 7和Java 8具有不同的API,因此调用旧的Java版本中不存在的API会导致此错误。
如果Eclipse Java构建路径被映射到7, 8,并且在Projo POM.XML Maven属性java.版本中提到了更高的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-at-work-with
或
添加(弹出窗口将打开)->
EDCOX1·2·Java 11支持Location:http://download.eclipse.org/eclipse/updates/4.9-p-builds
然后在POM.XML文件的Maven属性中更新Java版本,如下所示
1
2 3 |
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.target>${java.version}</maven.compiler.target> |
最后右键单击项目调试as->maven clean,maven build steps
正如上面提到的,可能会有各种各样的场景。一些帮助我解决这个问题的事情。
如果您使用Intellij
File -> 'Invalidate Caches/Restart'
或
被引用的类在另一个项目中,并且该依赖项没有添加到我的项目的Gradle构建文件中。所以我用
compile project(':anotherProject')
它奏效了。嗯!
有关提示,请仔细查看引发错误的类名和行号,例如:编译失败[错误] 应用程序xxxxx .java:[44,30]错误:找不到符号
另一个原因是不支持Java版本的方法,如JDK7 vs 8。检查您的%java_主页%
- 这和其他答案说的一样。
我也收到了这个错误。(我在谷歌上搜索了一下,然后就被转到了这一页)
问题:我正在从另一个项目B中定义的类调用项目A类中定义的静态方法。我收到以下错误:
1
|
error: cannot find symbol
|
解决方案:我通过首先在定义方法的项目中构建方法,然后从中调用方法的项目来解决这个问题。