如何排查can not find symbol的编译错误

原文连接http://stackoverflow.com/questions/25706216/what-does-a-cannot-find-symbol-compilation-error-mean

 

Cannotfind symbol意味着什么

首先,它是一个编译错误,意味着你的源代码有问题或者编译的方式有问题。

你的源代码有以下部分组成:

Ø  关键词:比如 true  false  class while等等

Ø  字面值:比如42  ’x’ 和 “Hi mum!” 等等

Ø  操作符和其他非字母数字符号:比如  +  =  { 等等

Ø  注释和空白格

 

一个cannot find symbol 报错就是关于标识符的。当你的代码编译时,编译器需要弄明白你你代码中每一个标识符的含义。而这类报错就意味着编译器不明白你代码指代的东西。

 

引起cannot findsymbol错误的原因

归根到底无非是因为编译器查找了所有标识符应该被定义的地方都找不到定义。有很多原因可以导致,常见的如下:

l  通用标识符

  • 名字拼写错误:比如StringBiudler而不是StringBuilder。Java不会试图弥补糟糕的拼写或输入错误
  • 大小写错误:比如stringBuilder而不是StringBuilder。所有的Java标识符是大小写敏感
  • 下划线使用不正确:比如mystring和my_string是不同的(如果你严格按照Java的风格规则,你就能很大程度避免这类错误)

l  变量标识符

  • 忘记声明变量
  • 变量声明范围无法覆盖你尝试使用的点

l  方法名标识符

 也许你试图引用一个继承的方法,而它却没在父/祖先类/接口中定义

l  类名标识符

  •  忘记导入类
  • 用了star 导入,但是该类却不在你导入的任何包中定义
  • 忘记new关键字使用:比如Strings=String();

通常问题可能是以上的几个原因导致。比如,也许你星号导入java.io.*并且尝试使用Files类(存在java.nio而不是java.io),其实你是想写File(存在java.io的类)

 

 

以下是一个不正确的变量方位导致”cannot find symbol”错误的例子:

for (int i = 0; i < strings.size(); i++) {

    if(strings.get(i).equalsIgnoreCase("fnoord")) {

        break;

    }

}

if (i < strings.size()) {

    ...

}

 

尽管我们预先声明了i,但是声明的范围只是在for 语句和循环体里面,而第二个if语句中的i引用是看不见这个声明。这里比较合适的修改是把第二个if语句挪进循环体,或者在循环之外重新声明一个i变量。

 

如果你是从命令行去编译的话还有可能是因为忘记编译或者重编译其他的类所以编译器就报该类错误。比如你有Foo和Bar类,其中Foo会使用到Bar。如果你忘记编译Bar而至直接跑javac Foo.java就会收到编译器报cannot find symbol错误。简单的解决就是直接javac Foo.java Bar.java 或者javac *.java。最好还是用java构建工具,如Ant,Maven,Gradle等等

 

如何修改该类错误

 

通常来讲,从弄明白引起报错原因下手,然后想想代码要做什么,最后选择正确的修改。

注意,并非所有修改都是合适的。比如这个

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

假设编译器报错“cannot findsymbol for j”,有很多方式可以修改:

  • 把里面的for 该为for (int j = 1;j < 10; j++ )       --很有可能对
  • 在里面或者外面的for循环前添加j声明,或者      --可能对
  • 在内循环把j改成I   --很有可能错

为了正确修改报错,关键是要理解你的代码想要做什么

 

模糊的原因

以下是一些”cannot find symbol”报错不大明朗的情况

1.        你没检查对源代码:这种情况发生在新手身上,他们还没弄清楚java工具链的工作流程或一个可重复构建的过程。比如使用IDE/Ant/Maven等等。这样情况下

2.        IDE问题:早有用户反馈IDE混淆或编译器找不到实际存在的类等问题

a)        如果IDE的缓存不能和文件系统同步就会发生报错。

b)        可能是IDE的Bug。比如@Joel Costigliola描述的Eclipse不能正确处理一个Maven “test”树的问题,参考http://stackoverflow.com/a/37207223/139985

3.        重定义系统类:有过编译器报错指出substring在如下场景是未知的符号,结果发现是程序员建立了自己的String类而该类中没有定义substring方法。(注意不要使用通用库类名来命名自己的类)

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

4.  同形字:如果你的源代码使用utf-8,那么有可能一些标识符存在形相似而义不同,因为utf-8中包含同形字。为避免这种情况,你可以通过只使用ASCII或者Latin-1来编码并且使用Java \uxxxx来转义其他字符。

没有更多推荐了,返回首页