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

发布于 2025-01-10 16:49:23 字数 170 浏览 0 评论 0原文

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

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

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

Please explain the following about "Cannot find symbol", "Cannot resolve symbol" or "Symbol not found" errors (in Java):

  • What do they mean?
  • What things can cause them?
  • How does the programmer go about fixing them?

This question is designed to seed a comprehensive Q&A about these common compilation errors in Java.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

月亮坠入山谷 2025-01-17 16:49:23

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

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

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

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

Java 源代码由以下部分组成:

  • 关键字:如 classwhile 等。
  • 文字:如 truefalse42'X'“嗨妈妈!”< /代码>。
  • 运算符和其他非字母数字标记:例如 +={ 等。
  • 标识符:如ReaderitoStringprocessEquibalancedElephants等。
  • 注释和空白。

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

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

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

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

  • 对于一般标识符:

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

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

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

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

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

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

       字符串字符串[] = ...
          if (strings.charAt(3)) { ... }
          // 也许应该是 'strings[0].charAt(3)'
      
  • 对于应该是类名的标识符:

    • 也许您忘记导入该类。

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

    • 也许您忘记了一个new,如下所示:

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

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

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

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

问题通常是上述问题的组合。例如,也许您“明星”导入了 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 循环的主体,因此之前的 ifor 语句中的 > 超出了块中的范围。


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

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

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

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

int res = tmp * (a + b);

如果从命令行编译,编译器可能找不到符号还有另一个原因。您可能只是忘记编译或重新编译其他一些类。例如,如果您有类 FooBar,其中 Foo 使用 Bar。如果您从未编译过 Bar 并且运行 javac Foo.java,您很容易发现编译器找不到符号 Bar 。简单的答案是将 FooBar 一起编译;例如,javac Foo.java Bar.javajavac *.java。或者最好还是使用 Java 构建工具;例如,AntMavenGradle 和 很快。

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

3. 如何修复这些错误?

一般来说,您首先要找出导致编译错误的原因。

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

然后你思考你的代码应该说什么。最后,您确定需要对源代码进行哪些修正才能实现您想要的功能。

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

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

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

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

关键是您需要了解您的代码正在尝试做什么,以便找到正确的修复方法。

4. 不明原因

以下是一些“找不到符号”似乎令人费解的情况……除非您仔细观察。

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

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

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

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

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

  5. IDE 问题:人们报告过他们的 IDE 出现混乱并且 IDE 中的编译器无法找到存在的类的情况......或者相反的情况。

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

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

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

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

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

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

    字符串 s = ...
    字符串 s1 = s.substring(1);
    

    事实证明,程序员创建了他们自己的 String 版本,并且他的类版本没有定义 substring 方法。我见过人们使用 SystemScanner 和其他类来执行此操作。

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

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

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

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


1 - 如果您确实在运行时异常或错误消息中看到此情况,则说明您已将 IDE 配置为运行带有编译错误的代码,或者您的应用程序正在生成和编译代码..在运行时。
2 - 土木工程的三个基本原则:水不往上流,木板往上流侧面更坚固,你无法推动绳子

0. Is there any difference between these errors?

Not really. "Cannot find symbol", "Cannot resolve symbol" and "Symbol not found" all mean the same thing. (Different Java compilers are written by different people, and different people use different phraseology to say the same thing.)

1. What does a "Cannot find symbol" error mean?

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.

Your Java source code consists of the following things:

  • Keywords: like class, while, and so on.
  • Literals: like true, false, 42, 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
  • Identifiers: like Reader, i, toString, processEquibalancedElephants, and so on.
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

2. What can cause a "Cannot find symbol" error?

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • For identifiers in general:

    • Perhaps you spelled the name incorrectly; i.e., StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
    • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
    • Perhaps you used underscores inappropriately; i.e., mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake...)
    • Perhaps you are trying to use something that was declared "somewhere else"; i.e. in a different context to where you have implicitly told the compiler to look. (A different class? A different scope? A different package? A different code-base?)
  • For identifiers that should refer to variables:

    • Perhaps you forgot to declare the variable.
    • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • For identifiers that should be method or field names:

    • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.

    • 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.

    • Perhaps you are trying to use a method as a field, or vice versa; e.g. "rope".length or someArray.length().

    • Perhaps you are mistakenly operating on an array rather than array element; e.g.,

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // Maybe that should be 'strings[0].charAt(3)'
      
  • For identifiers that should be class names:

    • Perhaps you forgot to import the class.

    • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.

    • Perhaps you forgot a new as in:

          String s = String();  // Should be 'new String()'
      
    • Perhaps you are trying to import or otherwise use a class that has been declared in the default package; i.e., the one where classes with no package statements go.

      Hint: learn about packages. You should only use the default package for simple applications that consist of one class ... or at a stretch, one Java source file.

  • For cases where type or instance doesn't appear to have the member (e.g., method or field) you were expecting it to have:

    • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
    • Perhaps you are shadowing a static or instance variable.
    • Perhaps you imported the wrong type; e.g., due to IDE completion or auto-correction may have suggested java.awt.List rather than java.util.List.
    • Perhaps you are using (compiling against) the wrong version of an API.
    • Perhaps you forgot to cast your object to an appropriate subclass.
    • Perhaps you have declared the variable's type to be a supertype of the one with the member you are looking for.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.


Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

List<String> strings = ...

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

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)


Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

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

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon ( ; ) before the {. The Java language syntax defines a semicolon in that context to be an empty statement. The empty statement then becomes the body of the for loop. So that code actually means this:

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

// The previous and following are separate statements!!

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

The { ... } block is NOT the body of the for loop, and therefore the previous declaration of i in the for statement is out of scope in the block.


Here is another example of "Cannot find symbol" error that is caused by a typo.

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

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to compile Foo and Bar together; e.g., javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g., Ant, Maven, Gradle and so on.

There are some other more obscure causes too ... which I will deal with below.

3. How do I fix these errors?

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

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

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

  • I could change the inner for to for (int j = 1; j < 10; j++) - probably correct.
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!
  • and so on.

The point is that you need to understand what your code is trying to do in order to find the right fix.

4. Obscure causes

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

  1. Incorrect dependencies: If you are using an IDE or a build tool that manages the build path and project dependencies, you may have made a mistake with the dependencies; e.g., left out a dependency, or selected the wrong version. If you are using a build tool (Ant, Maven, Gradle, etc), check the project's build file. If you are using an IDE, check the project's build path configuration.

  2. Cannot find symbol 'var': You are probably trying to compile source code that uses local variable type inference (i.e. a var declaration) with an older compiler or older --source level. The var was introduced in Java 10. Check your JDK version and your build files, and (if this occurs in an IDE), the IDE settings.

  3. You are not compiling / recompiling: It sometimes happens that new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like.

    Another example of this is when you use (Java 9+) java SomeClass.java to compile and run a class. If the class depends on another class that you haven't compiled (or recompiled), you are liable to get "Cannot resolve symbol" errors referring to the 2nd class. The other source file(s) are not automatically compiled. The java command's new "compile and run" mode is not designed for running programs with multiple source code files.

  4. An earlier build problem: It is possible that an earlier build failed in a way that gave a JAR file with missing classes. Such a failure would typically be noticed if you were using a build tool. However if you are getting JAR files from someone else, you are dependent on them building properly, and noticing errors. If you suspect this, use tar -tvf to list the contents of the suspect JAR file.

  5. IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

    • This could happen if the IDE has been configured with the wrong JDK version.

    • This could happen if the IDE's caches get out of sync with the file system. There are IDE specific ways to fix that.

    • This could be an IDE bug. For instance @Joel Costigliola described a scenario where Eclipse did not handle a Maven "test" tree correctly: see this answer. (Apparently that particular bug was been fixed a long time ago.)

  6. Android issues: When you are programming for Android, and you have "Cannot find symbol" errors related to R, be aware that the R symbols are defined by the context.xml file. Check that your context.xml file is correct and in the correct place, and that the corresponding R class file has been generated / compiled. Note that the Java symbols are case sensitive, so the corresponding XML ids are case sensitive too.

    Other symbol errors on Android are likely to be due to previously mention reasons; e.g., missing or incorrect dependencies, incorrect package names, method or fields that don't exist in a particular API version, spelling / typing errors, and so on.

  7. Hiding system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

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

    It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods. I've seen people do this with System, Scanner and other classes.

    Lesson: Don't define your own classes with the same names as common library classes!

    The problem can also be solved by using the fully qualified names. For example, in the example above, the programmer could have written:

    java.lang.String s = ...
    java.lang.String s1 = s.substring(1);
    
  8. Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

    You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.


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.

惟欲睡 2025-01-17 16:49:23

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

String s = String();

相反

String s = new String();

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

You'll also get this error if you forget a new:

String s = String();

versus

String s = new String();

because the call without the new keyword will try and look for a (local) method called String without arguments - and that method signature is likely not defined.

世俗缘 2025-01-17 16:49:23

已解决

使用IntelliJ

选择构建->重建项目将解决它

SOLVED

Using IntelliJ

Select Build->Rebuild Project will solve it

空宴 2025-01-17 16:49:23

再举一个“变量超出范围”的例子

由于我已经多次看到此类问题,也许再举一个例子来说明什么是非法的,即使它感觉 好的。

考虑这段代码:

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

如果你认为自己做了好事,那尤其糟糕。我在“优化”代码后看到过这种错误,如下所示:

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

“哦,有重复的代码,让我们把公共线拉出来”->就这样了。

处理这种范围问题的最常见方法是将 else 值预先分配给外部范围中的变量名称,然后在 if 中重新分配:

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

One more example of 'Variable is out of scope'

As I've seen that kind of questions a few times already, maybe one more example to what's illegal even if it might feel okay.

Consider this code:

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

That's invalid code. Because neither of the variables named message is visible outside of their respective scope - which would be the surrounding brackets {} in this case.

You might say: "But a variable named message is defined either way - so message is defined after the if".

But you'd be wrong.

Java has no free() or delete operators, so it has to rely on tracking variable scope to find out when variables are no longer used (together with references to these variables of cause).

It's especially bad if you thought you did something good. I've seen this kind of error after "optimizing" code like this:

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

"Oh, there's duplicated code, let's pull that common line out" -> and there it it.

The most common way to deal with this kind of scope-trouble would be to pre-assign the else-values to the variable names in the outside scope and then reassign in if:

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);
浅笑轻吟梦一曲 2025-01-17 16:49:23

Eclipse 中出现此错误的一种方法:

  1. 定义一个类 Asrc/test/java 中。
  2. src/main/java 中定义另一个使用类 A 的类 B

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

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

解决方案:

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

One way to get this error in Eclipse:

  1. Define a class A in src/test/java.
  2. Define another class B in src/main/java that uses class A.

Result: Eclipse will compile the code, but Maven will give "Cannot find symbol".

Underlying cause: Eclipse is using a combined build path for the main and test trees. Unfortunately, it does not support using different build paths for different parts of an Eclipse project, which is what Maven requires.

Solution:

  1. Don't define your dependencies that way; i.e., don't make this mistake.
  2. Regularly build your codebase using Maven so that you pick up this mistake early. One way to do that is to use a CI server.
日裸衫吸 2025-01-17 16:49:23

“找不到”意味着编译器找不到合适的变量、方法、类等。如果您收到错误消息,首先,您要找到收到错误消息的代码行。

然后您将能够在使用之前找到哪些变量、方法或类尚未定义。确认后,初始化该变量、方法或类,以便它可以用于稍后的require。考虑以下示例。

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

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);
    }
}

现在看看新的输出...

在此处输入图像描述

好的,我们成功解决了该错误。同时,如果你得到“找不到方法”或“找不到类”的信息,首先定义一个类或方法,然后使用它。

"Can not find " means that, the compiler who can't find an appropriate variable, method, class, etc. If you got that error massage, first of all, you want to find the code line where you get the error massage.

And then you will able to find which variable, method or class have not been defined before using it. After confirmation, initialize that variable, method or class, so it can be used for a later require. Consider the following example.

I'll create a demo class and print a name...

class demo {
    public static void main(String a[]) {
        System.out.print(name);
    }
}

Now look at the result..

Enter image description here

That error says, "variable name can not find". Defining and initializing value for 'name' variable can be abolished that error. Actually like this,

class demo {
    public static void main(String a[]) {

        String name = "smith";

        System.out.print(name);
    }
}

Now look at the new output...

Enter image description here

Ok, we successfully solved that error. At the same time, if you could get "can not find method " or "can not find class" something, at first, define a class or method and after use that.

哽咽笑 2025-01-17 16:49:23

正如人们在之前的答案中提到的那样,可能存在各种情况。以下是帮助我解决此问题的几件事。

  1. 如果您使用IntelliJ IDEA

    菜单文件使缓存无效/重新启动

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

    编译项目(':anotherProject')

    它成功了。

There can be various scenarios as people have mentioned in previous answers. Here are a couple of things which have helped me resolve this.

  1. If you are using IntelliJ IDEA

    Menu FileInvalidate Caches/Restart

or

  1. The class being referenced was in another project and that dependency was not added to the Gradle build file of my project. So I added the dependency using

    compile project(':anotherProject')

    And it worked.

不知在何时 2025-01-17 16:49:23

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

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

If you're getting this error in the build somewhere else, while your IDE says everything is perfectly fine, then check that you are using the same Java versions in both places.

For example, Java 7 and Java 8 have different APIs, so calling a non-existent API in an older Java version would cause this error.

痴情 2025-01-17 16:49:23

如果 Eclipse Java 构建路径映射到 7、8 并在项目中pom.xml 提到了 Maven 属性 java.version高于 7,8 的 Java 版本(9、10、11 等)需要在 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,位于使用

添加(将打开弹出窗口)->

名称: Java 11 支持
位置: 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 构建步骤。

If the Eclipse Java build path is mapped to 7, 8 and in the Project pom.xml Maven properties java.version is mentioned higher Java version (9, 10, 11, etc.) than 7,8 you need to update in the pom.xml file.

In Eclipse, if Java is mapped to Java version 11 and in pom.xml it is mapped to Java version 8. Update Eclipse support to Java 11 by going through the below steps in the Eclipse IDE

Menu HelpInstall New Software → paste the following link http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With

or

Add (Popup window will open) ->

Name: Java 11 support
Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

Then update the Java version in Maven properties of pom.xml file as below:

<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

Finally, do right click on the project Debug as -> Maven clean, Maven build steps.

关于从前 2025-01-17 16:49:23

我也遇到了这个错误(我用谷歌搜索并被引导到这个页面)。

问题:我从另一个项目 B 中定义的类调用项目 A 的类中定义的静态方法。

我收到以下错误:

error: cannot find symbol

解决方案:我解决了首先构建定义该方法的项目,然后构建调用该方法的项目。

I too was getting this error (for which I googled and I was directed to this page).

Problem: I was calling a static method defined in the class of a project A from a class defined in another project B.

I was getting the following error:

error: cannot find symbol

Solution: I resolved this by first building the project where the method is defined and then the project where the method was being called from.

阳光下的泡沫是彩色的 2025-01-17 16:49:23

您使用 mavencompile 编译了代码,使用 maventest 运行它,并且运行良好。现在,如果您更改了代码中的某些内容,然后在不编译的情况下运行它,您将收到此错误。

解决办法:重新编译然后运行测试。对我来说,它是这样工作的。

You compiled your code using maven compile, used maven test to run it, and it worked fine. Now if you changed something in your code and then without compiling you are running it, you will get this error.

Solution: Again compile it and then run test. For me it worked this way.

海未深 2025-01-17 16:49:23

我们在设置为 Gradle 多项目构建的 Java 项目中遇到错误。原来是其中一个子项目缺少 Gradle Java Library 插件
这阻止了子项目的类文件对构建中的其他项目可见。

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

plugins {
    ...
    id 'java-library'
}

We got the error in a Java project that is set up as a Gradle multi-project build. It turned out that one of the sub-projects was missing the Gradle Java Library plugin.
This prevented the sub-project's class files from being visible to other projects in the build.

After adding the Java library plugin to the sub-project's build.gradle in the following way, the error went away:

plugins {
    ...
    id 'java-library'
}
薯片软お妹 2025-01-17 16:49:23

我收到以下错误

java: cannot find symbol
  symbol: class __

要解决此问题,我尝试启用 Lombok,重新启动 IntelliJ IDEA 等,但下面的内容对我有用。

IntelliJ IDEA → 首选项编译器共享构建过程虚拟机选项并将其设置为

-Djps.track.ap.dependencies=false

然后运行

mvn clean install

I was getting the below error

java: cannot find symbol
  symbol: class __

To fix this, I tried enabling Lombok, restarted IntelliJ IDEA, etc., but the below worked for me.

IntelliJ IDEA → PreferencesCompilerShared Build process VM Options and set it to

-Djps.track.ap.dependencies=false

Then run

mvn clean install
公布 2025-01-17 16:49:23

有关提示,请仔细查看引发错误的类名和行号,例如:

Compilation failure
[ERROR] \applications\xxxxx.java:[44,30] error: cannot find symbol

另一个原因是 Java 版本不受支持的方法,例如 JDK 7 与 8。
检查您的 %JAVA_HOME% 环境变量

For hints, look closer at the class name that throws an error and the line number, example:

Compilation failure
[ERROR] \applications\xxxxx.java:[44,30] error: cannot find symbol

One other cause is an unsupported method for a Java version, say JDK 7 vs. 8.
Check your %JAVA_HOME% environment variable.

猫九 2025-01-17 16:49:23

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

  1. context.xml 文件从目录 src/java/package 移动到 resource 目录(IntelliJ IDE)
  2. 清理 target 目录。

In my case, I had to perform the below operations:

  1. Move the context.xml file from directory src/java/package to the resource directory (IntelliJ IDE)
  2. Clean the target directory.
舞袖。长 2025-01-17 16:49:23

回复:4.4:Stephen C 的出色回答

我在开发 OSGi 应用程序。
我有一个 Java 项目 A,它是 B 的依赖项。
构建B时,出现错误:

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

But in Eclipse< /a>,根本没有任何编译问题。

调查

当我查看A.jar时,有org.company.projectA.foo.abc的类,但没有的类org.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 包含所有预期的类,并且所有内容都可以编译。

Re: 4.4: An earlier build problem in Stephen C's excellent answer:

I encountered this scenario when developing an OSGi application.
I had a Java project A that was a dependency of B.
When building B, there was the error:

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

But in Eclipse, there wasn't any compile problem at all.

Investigation

When I looked in A.jar, there were classes for org.company.projectA.foo.abc, but none for org.company.projectA.bar.xyz.

The reason for the missing classes, was that in the A/pom.xml, there was an entry to export the relevant packages.

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

Solution

Add the missing packages like so:

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

And rebuild everything.

Now the A.jar includes all the expected classes, and everything compiles.

独享拥抱 2025-01-17 16:49:23

我在我的项目中观察到,如果代码中有一些错误,并且您正在使用 lombok,您可能会看到此错误,因为 lombok 注释处理未配置,或者因为初始错误 lombok 注释代码未注入源代码,但您可以在这种情况下修复代码并重试构建。

What i observed in my project is that if there is some error in code and if you're using lombok you may see this error because either lombok annotation processing not configured or because initial error lombok annotated codes are not injected to source code yet you can fix the code and retry building in this case.

塔塔猫 2025-01-17 16:49:23

我很高兴在 IDE 中使用 ! Optional.isEmpty(

),它工作得很好,因为我正在使用 >= JDK11。现在,当我在命令行上使用 Gradle 时(在 JDK 8),我在编译任务中遇到了令人讨厌的错误。

为什么?

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

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

Optional.isEmpty()

I was happily using !Optional.isEmpty() in my IDE, and it works fine, as I was compiling/running my project with >= JDK11. Now, when I use Gradle on the command line (running on JDK 8), I got the nasty error in the compile task.

Why?

From the documentation (pay attention to the last line):

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
苦笑流年记忆 2025-01-17 16:49:23

输入图片这里的描述

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

Enter image description here

I solved this error like this... The craziness of Android. I had the package name as "adapter" and then I refactored the name to the adapter with an "a" instead of "A" and solved the error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文