Answers:
并不是的。“找不到符号”和“无法解析符号”含义相同。一些Java编译器使用一个短语,而另一些使用。
首先,它是编译错误1。这意味着,无论有在Java源代码中的问题,或有在你编译它的方式有问题。
您的Java源代码包含以下内容:
true
,false
,class
,while
,等。42
和'X'
and "Hi mum!"
。+
,=
,{
,等等。Reader
,i
,toString
,processEquibalancedElephants
,等。“找不到符号”错误与标识符有关。编译代码时,编译器需要确定代码中每个标识符的含义。
“找不到符号”错误表示编译器无法执行此操作。您的代码似乎是指编译器无法理解的内容。
首先,只有一个原因。编译器查看了应该定义标识符的所有位置,但找不到该定义。这可能是由多种原因引起的。常见的如下:
StringBiulder
代替StringBuilder
。Java无法也不会尝试弥补拼写错误或输入错误。stringBuilder
代替StringBuilder
。所有Java标识符均区分大小写。mystring
和my_string
不同。(如果您坚持使用Java样式规则,则将在很大程度上避免出现此错误...)对于应为方法或字段名称的标识符:
"someString".push()
2。"someString".length
或someArray.length()
。也许您是错误地对数组而不是数组元素进行操作。例如
String strings[] = ...
if (strings.charAt(3)) { ... }
// maybe that should be 'strings[0].charAt(3)'
对于应为类名的标识符:
也许您忘记了new
:
String s = String(); // should be 'new String()'
对于类型或实例似乎没有成员的情况,您希望它具有:
问题通常是上述情况的组合。例如,也许您导入了“ star” java.io.*
,然后尝试使用Files
class中的java.nio
not java.io
。或者也许你打算写File
... ...这是的一个类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
的if
陈述。虽然我们先前声明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
循环的主体,因此i
该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
,您很有可能发现编译器找不到该符号Bar
。简单的答案是编译Foo
和Bar
在一起; 例如javac Foo.java Bar.java
或javac *.java
。或者最好还是使用Java构建工具;例如Ant,Maven,Gradle等。
还有一些其他更晦涩的原因...我将在下面处理。
一般来说,首先要弄清楚是什么导致了编译错误。
然后,您考虑一下您的代码应该说什么。然后,最后您确定需要对源代码进行哪些更正以执行所需的操作。
请注意,并非每个“更正”都是正确的。考虑一下:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
假设编译器为表示“找不到符号” j
。我可以通过多种方式“修复”该问题:
for
为for (int j = 1; j < 10; j++)
-可能是正确的。j
之前添加一个声明-可能正确。for
for
j
为i
内for
循环-可能是错误的!关键是您需要了解您的代码正在尝试做什么才能找到正确的修复程序。
在一些情况下,“找不到符号”似乎无法解释……直到您仔细观察。
不正确的依赖关系:如果您使用的是IDE或管理构建路径和项目依赖关系的构建工具,则可能是错误的依赖关系。例如遗漏了一个依赖项,或者选择了错误的版本。如果您使用的是构建工具(Ant,Maven,Gradle等),请检查项目的构建文件。如果使用的是IDE,请检查项目的构建路径配置。
您无需重新编译:有时候,新Java程序员可能不了解Java工具链的工作方式,或者没有实现可重复的“构建过程”;例如使用IDE,Ant,Maven,Gradle等。在这种情况下,程序员最终可能会追尾寻找一个虚幻的错误,该错误实际上是由于未正确地重新编译代码而导致的,等等。
较早的构建问题:较早的构建可能会失败,从而导致JAR文件缺少类。如果使用构建工具,通常会注意到这种故障。但是,如果要从其他人那里获取JAR文件,则取决于它们是否可以正确构建并注意到错误。如果您怀疑这一点,请使用tar -tvf
列出可疑JAR文件的内容。
IDE问题:人们已经报告了他们的IDE混乱并且IDE中的编译器找不到存在的类的情况……或相反的情况。
如果IDE配置了错误的JDK版本,则可能会发生这种情况。
如果IDE的缓存与文件系统不同步,则可能发生这种情况。有特定于IDE的方法可以解决此问题。
这可能是一个IDE错误。例如,@ Joel Costigliola描述了Eclipse无法正确处理Maven“测试”树的情况:请参见此答案。
Android问题:在为Android编程时,您遇到与相关的“找不到符号”错误R
,请注意,R
符号是由context.xml
文件定义的。检查您的context.xml
文件正确且正确的位置,以及相应的R
类文件是否已生成/编译。请注意,Java符号区分大小写,因此相应的XML ID也区分大小写。
Android上的其他符号错误可能是由于前面提到的原因引起的;例如,缺少或不正确的依赖项,不正确的程序包名称,在特定API版本中不存在的方法或字段,拼写/键入错误等。
重新定义系统类:我看到过这样的情况,编译器substring
在以下情况中抱怨说这是一个未知符号
String s = ...
String s1 = s.substring(1);
事实证明,程序员创建了自己的版本,String
而他的类版本未定义substring
方法。
课程:不要用与通用库类相同的名称定义自己的类!
同源符号: 如果对源文件使用UTF-8编码,则可能具有看起来相同但实际上不同的标识符,因为它们包含同源符号。有关更多信息,请参见此页面。
通过将自己限制为ASCII或Latin-1作为源文件编码,并对\uxxxx
其他字符使用Java 转义,可以避免这种情况。
1 -如果,或许,你也看到这个运行时异常或错误信息,那么无论你配置你的IDE来运行代码编译错误,或者您的应用程序生成和编译代码..在运行时。
2-土木工程的三个基本原则:水不上坡,木板在其侧面更坚固,并且您不能用力压绳子。
“变量超出范围”的另一个示例
正如我已经看过几次这样的问题一样,即使感觉还可以,也许还有另一个例子说明违法行为。
考虑以下代码:
if(somethingIsTrue()) {
String message = "Everything is fine";
} else {
String message = "We have an error";
}
System.out.println(message);
那是无效的代码。因为命名的变量message
在它们各自的作用域之外都不可见- {}
在这种情况下,将用括号括起来。
您可能会说:“但是以任何一种方式都定义了一个名为message的变量-因此message 是在if
“ 之后定义的。
但是你会错的。
Java没有free()
或delete
运算符,因此它必须依赖于跟踪变量范围来确定何时不再使用变量(以及对这些cause变量的引用)。
如果您认为自己做得很好,那就特别糟糕。在“优化”如下代码后,我已经看到这种错误:
if(somethingIsTrue()) {
String message = "Everything is fine";
System.out.println(message);
} else {
String message = "We have an error";
System.out.println(message);
}
“哦,有重复的代码,让我们拉出这条共同的线”->到那里。
处理这种范围问题的最常见方法是将else值预先分配给外部范围中的变量名,然后在以下情况下重新分配:
String message = "We have an error";
if(somethingIsTrue()) {
message = "Everything is fine";
}
System.out.println(message);
在Eclipse中获得此错误的一种方法:
A
在src/test/java
。B
中src/main/java
使用类A
。结果:Eclipse将编译代码,但是maven将给出“找不到符号”。
潜在原因:Eclipse对主树和测试树使用了组合的构建路径。不幸的是,它不支持为Eclipse项目的不同部分使用不同的构建路径,而这正是Maven所需要的。
解决方案:
“找不到”表示编译器找不到合适的变量,方法,类等...如果您遇到错误提示,首先您要找到获取错误提示的代码行。然后,您将找到能够在使用之前找到尚未定义的变量,方法或类。确认初始化后,该变量,方法或类可用于以后的需求...请考虑以下示例。
我将创建一个演示类并打印一个名称...
class demo{
public static void main(String a[]){
System.out.print(name);
}
}
现在看一下结果。
该错误表示“找不到变量名”。可以取消为“ name”变量定义和初始化值的错误。实际上,
class demo{
public static void main(String a[]){
String name="smith";
System.out.print(name);
}
}
现在看看新的输出...
好的,成功解决了该错误。同时,如果您得到“找不到方法”或“找不到类”的东西,请首先定义一个类或方法,然后再使用它。
我也收到此错误。(我为此搜索了Google,并将其定向到此页面)
问题:我正在从另一个项目B中定义的类中调用在项目A的类中定义的静态方法。出现以下错误:
error: cannot find symbol
解决方案:我首先通过建立定义方法的项目,然后再从其中调用方法的项目来解决此问题。
如果将eclipse Java构建路径映射到7、8,并且在Project pom.xml Maven属性中提到java.version的Java版本高于(9、10、11等),则需要在pom中进行更新,而不是7,8。 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构建步骤
就我而言-我必须执行以下操作:
context.xml
文件从移动src/java/package
到resource
目录(IntelliJ IDE)target
目录。