“找不到符号”编译错误是什么意思?

请解释以下关于“无法找到符号”错误:

  • 这个错误是什么意思?
  • 什么事情会导致这个错误?
  • 程序员如何去解决这个错误?
  • 这个问题被设计成一个关于Java中“无法找到符号”编译错误的综合性问题。


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

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

    您的Java源代码包含以下内容:

  • 关键词:像truefalseclasswhile等等。
  • 文字:像42'X'"Hi mum!"
  • 运算符和其他非字母数字令牌:如+={等等。
  • 标识符:像ReaderitoStringprocessEquibalancedElephants等。
  • 评论和空白。
  • “无法找到符号”错误是关于标识符。 编译代码时,编译器需要确定代码中每个标识符的含义。

    “无法找到符号”错误意味着编译器无法执行此操作。 你的代码似乎是指编译器不理解的东西。

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

    作为第一个订单,只有一个原因。 编译器查看了应该定义标识符的所有地方,并且找不到定义。 这可能是由许多因素造成的。 常见的如下:

  • 对于一般的标识符:
  • 也许你错误地拼写了这个名字; 即StringBiulder而不是StringBuilder 。 Java不能也不会试图补偿拼写错误或输入错误。
  • 也许你错了; 即stringBuilder而不是StringBuilder 。 所有Java标识符都区分大小写。
  • 也许你用不恰当的方式强调了; 即mystringmy_string是不同的。 (如果你坚持Java风格的规则,你将会在很大程度上免受这个错误的影响......)
  • 也许你正在尝试使用被宣布为“别的什么地方”的东西; 即在不同的上下文中,隐含地告诉编译器看看。 (一个不同的类?一个不同的范围?一个不同的包?一个不同的代码库?)
  • 对于应该引用变量的标识符:
  • 也许你忘了声明变量。
  • 也许变量声明超出了你试图使用它的地步。 (见下面的例子)
  • 对于应该是方法或字段名称的标识符:
  • 也许你正在试图引用未在父/祖类或接口中声明的继承方法或字段。
  • 也许你试图将方法用作字段,反之亦然; 例如"someString".lengthsomeArray.length()
  • 对于应该是类名称的标识符:

  • 也许你忘了导入课程。
  • 也许你使用了“明星”导入,但这个类没有在你导入的任何包中定义。
  • 也许你忘了一个new的:

    String s = String();  // should be 'new String()'
    
  • 对于类型或实例似乎没有您期望的成员的情况:

  • 也许你已经声明了一个嵌套类或一个泛型参数,它会影响你想要使用的类型。
  • 也许你正在遮蔽一个静态或实例变量。
  • 也许你输入了错误的类型; 例如由于IDE完成或自动更正。
  • 也许你正在使用(编译)一个API的错误版本。
  • 也许你忘了把你的对象转换成适当的子类。
  • 问题通常是上述的组合。 比如,也许你的“明星”进口java.io.* ,然后试图用Files类...这是java.niojava.io 。 或者也许你打算写File ...这是java.io一个类。


    下面是一个不正确的变量范围如何导致“无法找到符号”错误的例子:

    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 )。


    下面是一个导致拼写错误导致看似无法解释的“找不到符号”错误的例子:

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

    这会在println调用中给你一个编译错误,说i找不到。 但是(我听到你说)我确实宣布了!

    问题是{之前的鬼鬼祟祟的分号。 Java语言将其定义为空白语句。 所以这段代码实际上意味着:

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

    { ... }块不是for循环的主体,所以i的声明不在该块的范围内。


    这是另一个由错字造成的“无法找到符号”错误的例子。

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

    尽管与先前的声明中, tmptmp(...)的表达是错误的。 编译器会查找一个名为tmp的方法,并且找不到一个方法。 之前声明的tmp位于变量的名称空间中,而不是方法的名称空间。

    在我遇到的例子中,程序员实际上已经排除了一个操作员。 他打算写的是这样的:

    int res = tmp * (a + b);
    

    编译器在命令行编译时可能找不到符号还有另一个原因。 你可能只是忘记编译或重新编译其他类。 例如,如果您有FooBarFoo使用Bar课程。 如果你从未编译过Bar并运行javac Foo.java ,那么你很容易发现编译器找不到符号Bar 。 简单的答案是FooBar在一起; 例如javac Foo.java Bar.javajavac *.java 。 或者更好的是使用Java构建工具; 例如Ant,Maven,Gradle等。

    还有一些其他更晦涩的原因......我将在下面处理。

    3.我如何解决这些错误?

    一般来说,您首先要弄清楚导致编译错误的原因。

  • 查看编译错误消息指示的文件中的行。
  • 确定错误消息正在讨论哪个符号。
  • 找出编译器为什么说它找不到符号的原因; 往上看!
  • 然后你想想你的代码应该说什么。 然后,最后你找出你需要对你的源代码做什么修正来做你想做的。

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

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

    假设编译器对j表示“无法找到符号”。 有很多方法可以“修复”:

  • 我可以改变内部for for (int j = 1; j < 10; j++) - 可能是正确的。
  • 我可以在inner for循环之前为j添加一个声明,或者在outer for循环之前添加一个声明 - 可能是正确的。
  • 我可以改变ji在内for循环-可能是错的!
  • 等等。
  • 重点是你需要了解你的代码试图做什么,以找到正确的修复。

    4.不明原因

    以下是几个“无法找到符号”的情况,看起来似乎无法解释......直到你仔细观察。

  • 您正在查看错误的源代码 :经常发生的情况是,新的Java程序员不明白Java工具链如何工作,或者没有实现可重复的“构建过程”; 例如使用IDE,Ant,Maven,Gradle等。 在这种情况下,程序员最终可能会追逐他的尾巴寻找一个虚幻的错误,这实际上是由于没有正确地重新编译代码而造成的,等等......

  • IDE问题 :人们报告了他们的IDE感到困惑,并且IDE中的编译器无法找到存在的类或相反的情况。

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

  • 这可能是一个IDE错误。 例如@Joel Costigliola描述了一个Eclipse不能正确处理Maven“测试”树的场景: 查看这个答案

  • 重新定义系统类 :我见过编译器抱怨substring是一个未知符号的情况,如下所示

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

    事实证明,程序员已经创建了他们自己的String版本,并且他的版本没有定义substring方法。

    课程:不要使用与通用库类相同的名称定义自己的类!

  • 同态语言:如果您对源文件使用UTF-8编码,可能会使标识符看起来相同,但事实上不同,因为它们包含同类映射。 请参阅此页面了解更多信息。

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


  • 1 - 如果偶然发现运行时异常或错误消息中出现这种情况,那么要么您将IDE配置为运行带有编译错误的代码,要么您的应用程序正在运行时生成并编译代码。


    如果你忘记了一个new话,你也会得到这个错误:

    String s = String();
    

    String s = new String();
    

    “变量超出范围”的另一个例子是

    正如我已经多次看到过这样的问题,或许可以再举一个例子来证明什么是非法的,即使它可能感觉没问题。

    考虑这个代码:

    if(somethingIsTrue()) {
      String message = "Everything is fine";
    } else {
      String message = "We have an error";
    }
    System.out.println(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);
    }
    

    “哦,这里有重复的代码,让我们把这条公共线路拉出来 - ”然后就是它了。

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

    String message = "We have an error";
    if(somethingIsTrue()) {
      message = "Everything is fine";
    } 
    System.out.println(message);
    
    链接地址: http://www.djcxy.com/p/9373.html

    上一篇: What does a "Cannot find symbol" compilation error mean?

    下一篇: Unfortunately MyApp has stopped. How can I solve this?