请解释以下关于“找不到符号”、“无法解析符号”或“找不到符号”的错误(在Java中):
这个问题旨在产生一个全面的问题
“变量超出范围”的另一个示例
正如我已经见过几次这样的问题,也许再举一个例子来说明什么是非法的,即使它可能感觉不错。
考虑这个代码:
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);
}
“哦,有重复的代码,让我们把那条公共线拔出来”-
处理此类作用域问题的最常见方法是将else值预先分配给外部作用域中的变量名,然后在以下情况下重新分配:
String message = "We have an error";
if(somethingIsTrue()) {
message = "Everything is fine";
}
System.out.println(message);
如果您忘记了一个新的,也会出现此错误:
String s = String();
对
String s = new String();
因为没有
new
关键字的调用将尝试查找一个名为String
的(本地)方法,而该方法签名可能没有定义。
不是真的。“找不到符号”、“无法解析符号”和“找不到符号”都是同一个意思。不同的Java编译器使用不同的措辞。
首先,这是一个编译错误1。这意味着要么你的Java源代码有问题,要么你编译它的方式有问题。
Java源代码由以下内容组成:
类
,while
,等等
“找不到符号”错误是关于标识符的。编译代码时,编译器需要弄清楚代码中的每个标识符意味着什么。
“找不到符号”错误意味着编译器无法执行此操作。您的代码似乎引用了编译器不理解的内容。
首先,原因只有一个。编译器查找了所有应该定义标识符的地方,但找不到定义。这可能是由许多因素造成的。常见的有:
>
StringBiulder
而不是StringBuilder
。Java不能也不会尝试补偿错误的拼写或打字错误。stringBuilder
而不是StringBuilder
。所有Java标识符都区分大小写。mystring
和my_string
是不同的。(如果您坚持Java样式规则,您将在很大程度上避免这个错误...) 对于应引用变量的标识符:
对于应该是方法或字段名的标识符:
>
也许您正在尝试引用未在父/祖先类或接口中声明的继承方法或字段。
可能您试图引用的方法或字段在您使用的类型中不存在(即尚未声明);e、 g.“绳索”。按下()
2。
也许您正试图将方法用作字段,或者反之亦然;例如"绳". long
或一些rray.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
类...它在java.nio
而不是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()) {
...
}
这将在if
语句中为i
提供一个“找不到符号”错误。尽管我们之前声明了i
,但该声明仅适用于for
语句及其主体。if
语句中对i
的引用无法看到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
循环的主体,因此for
语句中先前的i
声明超出了块的范围。
这里是另一个由打字错误导致的“找不到符号”错误的例子。
int tmp = ...
int res = tmp(a + b);
尽管有前面的声明,
tmp(…)中的
tmp
表达式是错误的。编译器将查找名为tmp
的方法,但找不到。前面声明的tmp
位于变量的名称空间中,而不是方法的名称空间中。
在我遇到的例子中,程序员实际上漏掉了一个操作符。他想写的是:
int res = tmp * (a + b);
如果从命令行编译,编译器可能找不到符号还有另一个原因。您可能只是忘记编译或重新编译其他类。例如,如果您有类
Foo
和Bar
,其中Foo
使用Bar
。如果您从未编译过Bar
,并且运行过javac Foo。java
,您可能会发现编译器找不到符号条
。简单的答案是将Foo
和Bar
一起编译;e、 g.javac-Foo。java吧。java
或javac*。java
。或者最好还是使用Java构建工具;e、 g.蚂蚁、马文、格拉德尔等等。
还有一些其他更模糊的原因...我将在下面讨论。
一般来说,您首先要弄清楚是什么导致了编译错误。
查看编译错误消息指示的文件中的行
然后思考代码应该说什么。最后,你需要对你的源代码进行什么样的修改,以达到你的目的。
请注意,并非每个“更正”都是正确的。考虑一下:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
假设编译器对
j
说“找不到符号”。我有很多方法可以“修复”这个问题:
我可以将
的内部更改为(int j=1;j)的
关键是,为了找到正确的修复,您需要理解代码试图做什么。
这里有几个例子,“找不到符号”似乎令人费解。。。直到你仔细看。
>
不正确的依赖关系:如果您使用的是管理生成路径和项目依赖关系的IDE或生成工具,那么您可能在依赖关系方面犯了错误;e、 g.遗漏了依赖项,或选择了错误的版本。如果您正在使用构建工具(Ant、Maven、Gradle等),请检查项目的构建文件。如果您使用的是IDE,请检查项目的生成路径配置。
找不到符号“var”:您可能正试图用较旧的编译器或较旧的
--source
级别编译使用局部变量类型推断(即var
声明)的源代码。var
是在Java10中引入的。检查JDK版本和构建文件,以及(如果在IDE中发生这种情况)IDE设置。
您不是在编译/重新编译:有时新的Java程序员不了解Java工具链是如何工作的,或者没有实现可重复的“构建过程”;e、 g.使用IDE、Ant、Maven、Gradle等。在这种情况下,程序员可能会追尾寻找一个虚幻的错误,这实际上是由于没有正确地重新编译代码造成的,诸如此类。
另一个例子是使用(Java9)
JavaSomeClass。java来编译和运行类。如果该类依赖于您尚未编译(或重新编译)的另一个类,那么您很可能会遇到与第二个类有关的“无法解析符号”错误。其他源文件不会自动编译。
java
命令的新“编译并运行”模式不是为运行包含多个源代码文件的程序而设计的。
早期构建的一个问题:早期构建可能会失败,导致JAR文件缺少类。如果使用构建工具,通常会注意到这种故障。然而,如果你从其他人那里得到JAR文件,你需要依赖于它们的正确构建,并注意到错误。如果您怀疑这一点,请使用
tar-tvf
列出可疑JAR文件的内容。
IDE问题:人们报告过这样的情况:他们的IDE变得混乱,IDE中的编译器找不到存在的类。。。或者相反的情况。
>
如果IDE配置了错误的JDK版本,就会发生这种情况。
如果IDE的缓存与文件系统不同步,就会发生这种情况。有IDE特定的方法可以解决这个问题。
这可能是一个IDE错误。例如@Joel Costigliola描述了一个Eclipse没有正确处理Maven“测试”树的场景:看到这个答案了吗。(显然,这个特定的错误很久以前就被修复了。)
Android问题:当你为Android系统编程时,如果出现与
R
相关的“找不到符号”错误,请注意R
符号是由上下文定义的。xml
文件。检查你的上下文。xml
文件正确且位置正确,并且相应的R
类文件已生成/编译。请注意,Java符号区分大小写,因此相应的XML ID也区分大小写。
Android上的其他符号错误可能是由于前面提到的原因;e、 g.缺少或不正确的依赖项、不正确的包名、特定API版本中不存在的方法或字段、拼写/键入错误等。
隐藏系统类:我见过编译器抱怨
subString
是未知符号的情况,如下所示
String s = ...
String s1 = s.substring(1);
事实证明,程序员创建了自己版本的
String
,而他版本的类没有定义子字符串
方法。我见过人们用系统
,扫描仪
和其他课程来做这件事。
教训:不要用与公共库类相同的名称定义自己的类!
这个问题也可以通过使用完全限定的名称来解决。例如,在上面的例子中,程序员可以写:
java.lang.String s = ...
java.lang.String s1 = s.substring(1);
同形文字:如果您对源文件使用UTF-8编码,可能会有看起来相同但实际上不同的标识符,因为它们包含同形文字。有关详细信息,请参阅此页。
您可以通过将自己限制为ASCII或拉丁语-1作为源文件编码,并对其他字符使用Java
\uxxxx
转义来避免这种情况。
1-如果您可能在运行时异常或错误消息中看到这一点,那么您可能已经将IDE配置为运行带有编译错误的代码,或者您的应用程序正在生成和编译代码。。在运行时
2-土木工程的三个基本原则:水不会向上流动,木板的侧面更坚固,你不能推绳子
我的Android Studio不断给出错误,无法解析符号R。它是Android目录中名为R.java的文件。我已将此文件安全地保存在目录中。但它仍然显示出错误。在互联网上搜索到这个错误后,人们建议我重新构建/清理/升级项目同步/重新启动Android Studio和其他方法。我什么都做了。但问题仍然存在!怎么办??
我试图在我的Android项目中设置一个RecycerView,但是我不能引用我的列表,因为使用代码“RecycerView=view.findviewbyid(r.id.list)”给我的错误不能解析符号“list”。如果我尝试输入“R.ID”我找不到r.id.list,但我确定我给它的id是“list”。 我只是在代码中添加了依赖项和import语句。我试图重新同步和清理项目,但没有结果。 这
这里是我的导入: 这里是错误的代码: 这里是xml文件中RecyclerView的声明:
我的Android Studio一直在给出错误不能解析符号R。它是Android目录中的一个文件,名为r.java。我把这个文件安全地放在目录里。但是,它仍然显示出错误。在网上搜索到这个错误后,人们建议我做重建/清理/分级项目同步/重启Android Studio等方法。我什么都做了。但问题仍然存在!怎么办??
这里有一个类似的答案:如何在Java中将函数作为参数传递? 但提供的正确答案不起作用。我有一门课: 在函数内部我试图将传递到,但我得到的错误是: 找不到符号 符号:类Callable 我不知道为什么。 另外,我尝试使用返回类型字符串作为xMethod,您能传递一个返回类型不同的函数吗?
代码运行,但无法获得函数、类等的建议。 谢谢