轉自http://www.importnew.com/12425.html#cannt-find-symbolhtml
Java常見錯誤列表:java
碰見過上面沒有列舉的錯誤?若是有,那就在Piazza上提問吧,要在錯誤專欄(error folder)下吆。shell
當你在代碼中引用一個沒有聲明的變量時通常會報這個錯誤。考慮下面的例子:express
1
2
3
4
5
6
7
8
9
10
|
public class Test {
public static void main(String[] args) {
int a = 3 ;
int b = 4 ;
int c = 20 ;
average = (a + b + c)/ 5.0 ;
System.out.println(average);
}
}
|
1
2
3
4
5
|
1 error found:
File: Test.java <hr>
Error: Test.java:7: cannot find symbol
symbol : variable average
location: class Test
|
在上面的例子中,變量average沒有被聲明——也就是說你須要告訴編譯器average的類型是什麼,例如:數組
1
|
double average = (a + b + c)/ 5.0 ;
|
此外,當你在代碼中引用一個方法但沒有在方法名後加上括號時也會報這個錯誤,加上括號用以代表引用的是個函數,即便當函數沒有參數時也不能省略括號。例如:app
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
my_method;
}
public static void my_method() {
System.out.println( "Hello, world!" );
}
}
|
1
2
3
4
5
|
1 error found:
File: Test.java <hr>
Error: Test.java:7: cannot find symbol
symbol : variable my_method
location: class Test
|
在上面的例子中,編譯器在main方法中查找名爲my_method的變量,實際上,你是想調用一個叫作my_method的方法:ide
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
my_method();
}
public static void my_method() {
System.out.println( "Hello, world!" );
}
}
|
第三種狀況,若是你忘記導入你所使用的包時也會出現這個錯誤。例如,考慮下面這個從用戶那裏讀入一個整數的例子:函數
1
2
3
4
5
6
|
public class Test {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
int n = console.nextInt();
}
}
|
1
2
3
4
5
6
7
8
9
|
2 errors found:
File: Test.java <hr>
Error: cannot find symbol
symbol: class Scanner
location: class Test
File: Test.java <hr>
Error: cannot find symbol
symbol: class Scanner
location: class Test
|
這裏的問題是程序必須導入java.util.Scanner(或者java.util.)。不然,編譯器不知道Scanner是什麼類型。當你在處理文件的輸入/輸出時,若是忘記導入java.util.Arrays或者java.io.,也會遇到這個錯誤。ui
1
2
3
4
5
6
7
|
import java.util.*; // or --> import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
int n = console.nextInt();
}
}
|
最後,當咱們在使用大小敏感的變量名時也會遇到這個錯誤。Java中全部的標識符(identifiers)都是區分大小寫的。這就意味着,若是咱們聲明瞭一個名爲average的變量,而後在後面用Average引用它時,編譯器就會報找不到Average這個變量的錯誤。google
在一個Java程序中,若是類名與文件名不匹配時會報這個錯。例如,下面這個Foo.java程序:
1
2
3
4
5
|
public class Bar {
public static void main(String[] args) {
System.out.println( "Hello, world!" );
}
}
|
1
2
3
|
1 error found:
File: Foo.java <hr>
Error: class Bar is public, should be declared in a file named Bar.java
|
因爲Foo與Bar不匹配,這段代碼會編譯失敗。修改這個錯誤,咱們既能夠修改類名,也能夠修改文件名。
這個錯誤是一種與大括號有關的錯誤,通常來講,這個錯誤發生在程序最後有太多大括號時;例如:
1
2
3
4
5
6
|
public class Test {
public static void main(String[] args) {
System.out.println( "Hello!" );
}
}
}
|
1
2
3
|
1 error found:
File: Test.java <hr>
Error: class, interface, or enum expected
|
一種找出這種錯誤的方式是正確的縮進代碼(由於這種錯誤老是與大括號有關)。咱們能夠在Dr.java中按組合鍵CTRL-A(去選中這個程序),而後按TAB鍵(來正確地縮減代碼)。在咱們上面的實例代碼中,程序的最後有兩個大括號,這在一個合法的程序中是不可能出現的。所以,咱們僅僅去掉一個大括號就可以讓程序正確的編譯。
1
2
3
4
5
|
public class Test {
public static void main(String[] args) {
System.out.println( "Hello!" );
}
}
|
當編譯器檢查到代碼中缺失字符時會出現」缺失X」這種形式的錯誤,錯誤信息會告訴你在哪行缺失了哪一個字符,考慮下面的程序:
1
2
3
4
5
6
7
8
9
|
public class Test
public static void main(String[] args) {
my_method();
}
public static void my_method() {
System.out.println( "Hello, world!" )
}
}
|
1
2
3
4
5
|
2 errors found:
File: Test.java <hr>
Error: Test.java:1: '{' expected
File:.java <hr>
Error: Test.java:7: ';' expected
|
這個錯誤信息告訴你在第1行缺失了一個大括號,在第7行缺失了一個分號。解決這種錯誤很簡單——只需把缺失的字符在正確的位置上補上便可。
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
my_method();
}
public static void my_method() {
System.out.println( "Hello, world!" );
}
}
|
當把代碼寫在了方法外時會出現這個錯誤;這種錯誤通常也是由大括號引發的。考慮下面的例子:
1
2
3
4
5
6
7
|
public class Test {
System.out.println( "Hello!" );
public static void main(String[] args) {
System.out.println( "World!" );
}
}
|
1
2
3
4
5
|
2 errors found:
File: Test.java <hr>
Error: <identifier> expected
File: Test.java <hr>
Error: illegal start of type
|
在這種狀況下,很明顯第一個打印語句應該放在main方法裏面,這樣才能經過編譯。然而,當咱們的程序中有多於一個方法而且大括號也不匹配時,這種「缺失標識符」的錯誤就不容易被發現了:
1
2
3
4
5
6
|
public class Test {
public static void main(String[] args) {
System.out.println( "Hello!" );}
System.out.println( "World!" );
}
}
|
1
2
3
4
5
6
7
|
3 errors found:
File: Test.java <hr>
Error: <identifier> expected
File: Test.java <hr>
Error: illegal start of type
File: Test.java <hr>
Error: class, interface, or enum expected
|
在上面的代碼中多了一個大括號,可是由於代碼沒有正確的縮進,因此很難找出這個錯誤。這樣使得main方法在打印「hello」語句後就結束了,這樣打印「world」的語句就變成方法之外的代碼了。修改這個錯誤的方式十分簡單——只須要把第三行的大括號刪除就能夠了:
1
2
3
4
5
6
|
public class Test {
public static void main(String[] args) {
System.out.println( "Hello!" );
System.out.println( "World!" );
}
}
|
當編譯器遇到一條不合法的語句時會報「非法的表達式開頭」這種錯誤。考慮下面的例子:
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
my_method();
public static void my_method() {
System.out.println( "Hello, world!" );
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
5 errors found:
File: Test.java <hr>
Error: Test.java:6: illegal start of expression
File: Test.java <hr>
Error: Test.java:6: illegal start of expression
File: Test.java <hr>
Error: Test.java:6: ';' expected
File: Test.java <hr>
Error: Test.java:6: ';' expected
File: Test.java <hr>
Error: Test.java:9: reached end of file while parsing
|
這裏,缺乏了一個關閉main方法大括號。因爲main方法沒有被關閉,編譯器把調用my_method方法以後的代碼也看成main方法的一部分。然而,後面的代碼是public static void my_method() {,很顯然,這在一個方法內不合法。
「非法的表達式開頭」這種錯誤不如咱們上面提到的「××缺失」這種信息有幫助。對於這種錯誤(以及不少其餘一些錯誤),很是有必要檢查一下出錯代碼前面的那幾行。對於上面那個例子,咱們只須要在編譯器報錯的那行前面加上大括號關閉main方法就能夠了。從新編譯,全部的錯誤都解決了。
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
my_method();
}
public static void my_method() {
System.out.println( "Hello, world!" );
}
}
|
當你的程序在處理類型相關的問題時會報這個錯。咱們能夠對一些類型進行相互轉化,例如,你能夠輕鬆把一個char類型轉爲int類型,反之亦然;你也能夠經過向上轉型把一個double類型轉爲int類型。可是,你不能把基本類型與像String這樣的對象進行相互轉換。例如:
1
2
3
4
5
|
public class Test {
public static void main(String[] args) {
int num = "Hello, world!" ;
}
}
|
1
2
3
4
5
|
1 error found:
File: Test.java <hr>
Error: Test.java:3: incompatible types
found : java.lang.String
required: int
|
通常來講,你不能像解決其餘一些錯誤同樣解決這種錯誤。這不是一種語法錯誤,而是一種關於類型的邏輯錯誤。把一個String類型轉爲int類型通常來講都是毫無心義。可是,在一些應用中,你可能須要把String類型轉爲int類型,好比,當這個字符串代碼一個數字時:
1
2
3
4
5
|
public class Test {
public static void main(String[] args) {
int num = "500" ;
}
}
|
1
2
3
4
5
|
1 error found:
File: Test.java <hr>
Error: Test.java:3: incompatible types
found : java.lang.String
required: int
|
解決這種錯誤通常採用這樣的方法:藉助於Java中像Integer這樣的類,這些基本類型的包裝類中有能接受字符串類型的參數的方法,這樣就把字符串類型轉爲整型了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class Test {
public static void main(String[] args) {
int num = Integer.parseInt(" 500 ");
}
}
```
可是,這種解決「類型不兼容」錯誤的方案是一種例外,不是什麼規則,由於這種錯誤通常來自於邏輯上的錯誤。
<a name= "invalid-method" /></a>
### 8 . 非法的方法聲明;須要返回類型
在Java中的每一個方法都要求明確的聲明返回類型,即便這個方法什麼也不返回,也要用 void 進行標識,就像main方法那樣。
當一個方法沒有聲明返回類型時,會出現這種錯誤:
<pre class ="brush: java; gutter: true ; first-line: 1 ; highlight: []; html-script: false ">
public class Test {
public static void main(String[] args) {
int x = getValue();
System.out.println(x);
}
public static getValue() {
return 10 ;
}
}
|
1
2
3
|
1 error found:
File: Test.java <hr>
Error: Test.java:7: invalid method declaration; return type required
|
解決這種問題,在方法聲明處加上合適的返回類型便可:
1
2
3
4
5
6
7
8
9
10
|
public class Test {
public static void main(String[] args) {
int x = getValue();
System.out.println(x);
}
public static int getValue() {
return 10 ;
}
}
|
當你使用不合法的索引訪問數組時會報數組越界這種錯誤,數組arr的合法錯誤範圍是[0, arr.length-1];當你訪問這以外的索引時會報這個錯。例如:
1
2
3
4
5
6
7
8
|
public class Test {
public static void main(String[] args) {
int [] arr = { 1 , 2 , 3 };
for ( int i = 0 ; i <= arr.length; i++) {
System.out.println(arr[i]);
}
}
}
|
1
2
3
4
5
6
7
|
java.lang.ArrayIndexOutOfBoundsException: 3
at Test.main(Test.java:5)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
|
這種錯誤很像咱們下面即將說的字符串索引越界,這種錯誤的錯誤信息後面部分與錯誤不大相關。可是,第1行就告訴咱們錯誤的緣由是數組越界了,在咱們上面的例子,非法的索引值是3,下面一行的錯誤信息告訴你錯誤發生在Test類的第5行上,在main方法以內。
在上面的例子中,由於咱們循環過多致使出現這個錯誤,循環索引i最大能夠爲4,而4超過了數組的長度,所以越界了。相反,i的上界應該使用<或者相同效果的語句來界定。
1
2
3
4
5
6
7
8
|
public class Test {
public static void main(String[] args) {
int [] arr = { 1 , 2 , 3 };
for ( int i = 0 ; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
|
當處理數組越界時,打印出遍歷數組的索引十分有幫助,這樣咱們就可以跟蹤代碼找到爲何索引達到了一個非法的值。
當你在程序中去訪問一個字符串的非法索引時會報字符串索引越界這個錯誤。一個String的合法索引範圍是[0,str.leng()-1];當你訪問這以外的索引時會報這個錯。例如:
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
String str = "Hello, world!" ;
String a = str.substring(- 1 , 3 );
String b = str.charAt(str.length());
String c = str.substring( 0 , 20 );
}
}
|
1
2
3
4
5
6
7
8
|
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at Test.main(Test.java:5)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:271)
|
這種錯誤的錯誤信息後面部分與錯誤不大相關。可是,第1行就說明了錯誤的地方是字符串的索引,在咱們這個例子,非法的索引是-1,下面一行錯誤信息告訴咱們這個錯誤是在執行substring方法時拋出的,發生錯誤的位置是Test類的第5行。這種與錯誤相關的程序軌跡告訴咱們程序是在調用哪一個方式時出的錯,這樣咱們就能追蹤代碼,並最終改正它。
值得注意的是,上面程序中的a,b,c都會拋出這種錯誤,可是程序在遇到第一個錯誤時就被迫終止了。
這不是編譯時的錯誤,而是運行時的錯誤。換句話說,編譯器能正確編譯這段程序由於它只是在邏輯上有錯,此外,在程序運行以前,咱們也無法預料是否會有錯誤發生。解決這種錯誤,咱們須要改正程序的邏輯來保證沒有地方訪問非法的索引。
當你在調用函數時參數數量或順序不對時會報這個錯誤。例如,考慮下面的程序:
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
myMethod( 1.0 , 2 , "Hello!" );
}
public static void myMethod( double d, String s, int x) {
System.out.println(s + " " + d + " " + x);
}
}
|
1
2
3
4
5
6
|
1 error found:
File: Test.java <hr>
Error: method myMethod in class Test cannot be applied to given types;
required: double,java.lang.String,int
found: double,int,java.lang.String
reason: actual argument int cannot be converted to java.lang.String by method invocation conversion
|
這種錯誤的錯誤信息很是有幫助。「required」這一行錯誤信息告訴咱們方法的參數是什麼,方法的參數列表在這後面。在上面的例子中,myMethod方法的參數前後順序應該是double類型、String類型,最後是一個int類型的變量。
錯誤信息的下一行(found開頭的這一行)告訴咱們程序在調用這個方法時用了什麼樣的參數。在上面的例子中,是一個double類型,一個int類型,最後是一個String類型的變量,很顯然順序是不對的。
解決這種錯誤,咱們須要保證方法的參數個數和類型與函數聲明時都一致才行。
1
2
3
4
5
6
7
8
9
|
public class Test {
public static void main(String[] args) {
myMethod( 1.0 , "Hello!" , 2 );
}
public static void myMethod( double d, String s, int x) {
System.out.println(s + " " + d + " " + x);
}
}
|
當你聲明一個方法有返回值可是沒有寫return語句時會報這個錯誤。例如:
1
2
3
4
5
6
7
8
9
10
|
public class Test {
public static void main(String[] args) {
int x = twice( 5 );
System.out.println(x);
}
public static int twice( int x) {
int value = 2 * x;
}
}
|
1
2
3
|
1 error found:
File: Test.java <hr>
Error: Test.java:9: missing return statement
|
咱們經過函數聲明告知編譯器twice方法會返回一個int值,可是咱們沒有寫return語句:
1
2
3
4
5
6
7
8
9
10
11
|
public class Test {
public static void main(String[] args) {
int x = twice( 5 );
System.out.println(x);
}
public static int twice( int x) {
int value = 2 * x;
return value;
}
}
|
在某些if條件句中,編譯器也會認爲函數沒有返回值。像下面這個例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class Test {
public static void main(String[] args) {
int x = absVal(- 5 );
System.out.println(x);
}
public static int absVal( int x) {
if (x < 0 ) {
return -x;
}
if (x >= 0 ) {
return x;
}
}
}
|