在開發 Java 軟體時可能會遇到許多類型的錯誤,但大多數可以避免。 我們列舉了 50 個最常見的 Java 軟體錯誤,其中包含代碼示例和教程,以幫助您解決常見的編碼問題。
如果您正在使用 .NET,您還應該查看我們的 50 個最常見的 .NET 軟體錯誤指南,以及如何避免這些錯誤。 如果您當前的挑戰與 Java 相關,請繼續閱讀以了解最常見的問題及其解決方法。
編譯器錯誤消息在Java軟體代碼在編譯器執行時產生。需要重點記住的是,一個編譯器可能為一個錯誤拋出多個錯誤消息。所以修復第一個錯誤並重編譯,就能修復很多的問題。
當編碼出現遺漏時,就會發生這類錯誤。可能是缺失了一個括號或者分號。
private static double volume(String solidom, double alturam, double areaBasem, double raiom) { double vol; if (solidom.equalsIgnoreCase("esfera"){ vol=(4.0/3)*Math.pi*Math.pow(raiom,3); } else { if (solidom.equalsIgnoreCase("cilindro") { vol=Math.pi*Math.pow(raiom,2)*alturam; } else { vol=(1.0/3)*Math.pi*Math.pow(raiom,2)*alturam; } } return vol;}
這種錯誤消息常常不會準確的定位到錯誤發生的位置。為了找到錯誤,建議:
「未封閉的 String 表達式」錯誤消息發生在 Sting 表達式結束時沒有引號標記,錯誤消息將在發生錯誤的同一行提示出來。一個 String 表達式在源碼中是一個值。
public abstract class NFLPlayersReference { private static Runningback[] nflplayersreference; private static Quarterback[] players; private static WideReceiver[] nflplayers; public static void main(String args[]){ Runningback r = new Runningback("Thomlinsion"); Quarterback q = new Quarterback("Tom Brady"); WideReceiver w = new WideReceiver("Steve Smith"); NFLPlayersReference[] NFLPlayersReference; Run(); nflplayersreference[0] = r; players[1] = q; nflplayers[2] = w; for ( int i = 0; i < nflplayersreference.length; i++ ) { System.out.println("My name is " + " nflplayersreference[i].getName()); nflplayersreference[i].run(); nflplayersreference[i].run(); nflplayersreference[i].run(); System.out.println("NFL offensive threats have great running abilities!"); } } private static void Run() { System.out.println("Not yet implemented"); } }
通常情況下,錯誤發生在:
String 表達式結束時沒有使用引號標記。這種錯誤只要在 String 表達式結束是使用引號就能簡單的改正
String 表達式超過一行時。長的 String 表達式可以被拆分成多個表達式,然後用 "+" 連接起來。
引號是 String 表達式中的元素又沒有使用下劃線「\」進行轉義。
3. 「非法的表達式開頭」
出現「非法表達式開頭」錯誤的原因有很多。但它最終歸類於一個不太有用的錯誤消息之一。有些開發者說這是由糟糕的代碼造成的。
通常,創建表達式是用於生成新值或為變量賦值。編譯器期望找到一個表達式,但找不到它,因為語法不符合預期。 在下面這些語句中可以找到此錯誤。
} public void newShape(String shape) { switch (shape) { case "Line": Shape line = new Line(startX, startY, endX, endY); shapes.add(line); break; case "Oval": Shape oval = new Oval(startX, startY, endX, endY); shapes.add(oval); break; case "Rectangle": Shape rectangle = new Rectangle(startX, startY, endX, endY); shapes.add(rectangle); break; default: System.out.println("ERROR. Check logic."); } } } }
4. 「找不到符號」這是一個非常常見的問題,因為 Java 中的所有標識符都需要在使用之前進行聲明。 當編譯代碼時,編譯器並不理解標識符的含義。
在你遇到「找不到符號」消息時可能有很多種原因:
標識符聲明時的拼寫可能與代碼中使用時的拼寫不同。
該變量從未被聲明。
該變量使用的位置與其聲明的作用域不同。
類並未被導入。
5. 「公共類 XXX 應該在文件中出現」
「公共類 XXX 應該在文件中出現」這個消息出現在類XXX和Java程序文件名不一致時。原始碼只有在類名和 Java 文件名一樣時才會被編譯:
package javaapplication3; public class Robot { int xlocation; int ylocation; String name; static int ccount = 0; public Robot(int xxlocation, int yylocation, String nname) { xlocation = xxlocation; ylocation = yylocation; name = nname; ccount++; } } public class JavaApplication1 { public static void main(String[] args) { robot firstRobot = new Robot(34,51,"yossi"); System.out.println("numebr of robots is now " + Robot.ccount); } }
要修復這種情況:
6. 「不兼容類型」「不兼容的類型」是在賦值語句中嘗試將變量與類型表達式匹配時觸發的邏輯錯誤。通常是在代碼嘗試將文本字符寫入到整數中時出現,反之亦然。 這不是 Java 語法錯誤。
test.java:78: error: incompatible typesreturn stringBuilder.toString(); ^required: intfound: String1 error
當編譯器給出「不兼容的類型」消息時,確實沒有一個簡單的修複方案:
有可以轉換類型的函數。
開發人員可能需要按照代碼的預期修改之。
7. 「無效的方法聲明;需求返回類型」此錯誤表示方法籤名中沒有明確說明方法的返回類型。
public class Circle{ private double radius; public CircleR(double r) { radius = r; } public diameter() { double d = radius * 2; return d; }}
有幾種方式會觸發「無效的方法聲明; 需求返回類型「錯誤:
8. 「類 Y 中的方法 X 不能應用於給定類型」此錯誤消息是 Java 中最有用的錯誤消息之一。 它解釋了方法籤名是如何調用錯誤參數的。
RandomNumbers.java:9: error: method generateNumbers in class RandomNumbers cannot be applied to given types;generateNumbers();required: int[]found:generateNumbers();reason: actual and formal argument lists differ in length
方法在被調用時期望獲取在方法聲明中定義的某些參數。 檢查方法聲明、謹慎調用方法,以確保聲明和調用的參數是兼容的。
9. 「缺少返回語句」當一個方法缺少返回語句時,會發生「缺少返回語句」錯誤。 每一個有返回值的方法(非 void 類型)必須有一句字面上的語句用以返回返回值,以便在方法外調用該值。
public String[] OpenFile() throws IOException { Map<String, Double> map = new HashMap(); FileReader fr = new FileReader("money.txt"); BufferedReader br = new BufferedReader(fr); try{ while (br.ready()){ String str = br.readLine(); String[] list = str.split(" "); System.out.println(list); } } catch (IOException e){ System.err.println("Error - IOException!"); }}
下面列舉了一些編譯器拋出「缺少返回語句」的消息的原因:
當將超過一個變量可以保存的信息分配給該變量時,會發生「精度可能丟失」問題。如果發生這種情況,超出的信息將會被扔掉。如果這樣做沒問題,那麼代碼需要將變量顯式地聲明為新類型。
下面情況會發生「精度可能丟失」錯誤:
將一個實數賦值給一個整型變量。
將一個雙精度浮點數賦值給一個整型變量。
Java 中原始數據類型解析展示了數據是怎麼表示的。
11. 「解析時到達文件末尾」
這個錯誤信息經常發生在 Java 程序缺少「}」符號時。通常在代碼末加上「}」符號能很快解決這個問題。
public class mod_MyMod extends BaseModpublic String Version(){ return "1.2_02";}public void AddRecipes(CraftingManager recipes){ recipes.addRecipe(new ItemStack(Item.diamond), new Object[] { "#", Character.valueOf('#'), Block.dirt });}
上述代碼的運行結果是下列錯誤:
java:11: reached end of file while parsing }
代碼編寫工具和適當的代碼縮進可以更容易地找到這些不對的大括號。
「語句不可達」發生在當語句被放在一個不會被執行的位置時候。通常是在 break 語句或 return 語句後面。
for(;;){ break; ... }int i=1;if(i==1) ...else ...
通常簡單地移動 return 語句就能解決這個錯誤。
13. 「變量 x 可能未被初始化」
這個問題發生在當方法內局部變量在聲明時沒有被初始化的時候。當一個變量未被初始化但是出現在 if 語句中的時候會發生該錯誤。
int x;if (condition) { x = 5;}System.out.println(x);
14. 「操作符 ... 不能應用於 x」這個情況發生於當操作符應用於沒有定義其使用方法的類型上。
operator < cannot be applied to java.lang.Object,java.lang.Object
當 Java 代碼嘗試使用 string 類型進行數學計算時會經常出現這個問題。為了解決它,string 需要被轉化為 integer 或 float。
15. 「不能轉換的類型」「不能轉換的類型」錯誤發生在 Java 代碼嘗試進行非法轉換的時候。
TypeInvocationConversionTest.java:12: inconvertible typesfound : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>required: java.util.ArrayList<java.lang.Class<?>> lessRestrictiveClassList = (ArrayList<Class<?>>) classList; ^
例如,boolean 不能轉換為 int。
16. 「缺少返回值」當返回語句返回一個錯誤的類型時,你就會收到「缺少返回值」消息。例如下列代碼:
public class SavingsAcc2 { private double balance; private double interest; public SavingsAcc2() { balance = 0.0; interest = 6.17; } public SavingsAcc2(double initBalance, double interested) { balance = initBalance; interest = interested; } public SavingsAcc2 deposit(double amount) { balance = balance + amount; return; } public SavingsAcc2 withdraw(double amount) { balance = balance - amount; return; } public SavingsAcc2 addInterest(double interest) { balance = balance * (interest / 100) + balance; return; } public double getBalance() { return balance; }}
返回下列錯誤信息:
SavingsAcc2.java:29: missing return value return; ^ SavingsAcc2.java:35: missing return value return; ^ SavingsAcc2.java:41: missing return value return; ^ 3 errors
通常,那些返回語句沒有返回任何東西。
17. 「返回類型為 void 的方法不能返回一個值」當一個返回類型為 void 的方法嘗試返回任何值的時候就會發生這個 Java 錯誤,例如下面的例子:
public static void move(){ System.out.println("What do you want to do?"); Scanner scan = new Scanner(System.in); int userMove = scan.nextInt(); return userMove;}public static void usersMove(String playerName, int gesture){ int userMove = move(); if (userMove == -1) { break; }
通常改變方法籤名,使之和返回語句的返回類型相配就能解決這個問題。在上述例子中,void 可以改為 int:
public static int move(){ System.out.println("What do you want to do?"); Scanner scan = new Scanner(System.in); int userMove = scan.nextInt(); return userMove;}
18. 「非靜態變量 ... 不能在靜態上下文中被引用」當編譯器嘗試在一個靜態方法中訪問一個非靜態變量時會發生該錯誤 :
public class StaticTest { private int count=0; public static void main(String args[]) throws IOException { count++; }}
為了解決「非靜態變量 ... 不能在靜態上下文中被引用」的錯誤,有下述兩種方法:
在籤名中將變量聲明為靜態變量。
在靜態方法中創建一個非靜態對象的示例
19. 「非靜態方法 ... 不能在靜態上下文中被引用」這個情況發生在 Java 代碼嘗試在非靜態類中調用非靜態方法的時候。例如下述代碼:
class Sample{ private int age; public void setAge(int a) { age=a; } public int getAge() { return age; } public static void main(String args[]) { System.out.println("Age is:"+ getAge()); }}
將會返回下述錯誤:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Cannot make a static reference to the non-static method getAge() from the type Sample
為了在靜態方法中調用非靜態方法,可以聲明一個類的實例來調用這個非靜態方法。
20. 「(array) <X> Not Initialized」 (數組未初始化)當數組已聲明但未初始化時,你將得到「(array)<X>未初始化」的消息。 數組的長度是固定的,因此每個數組都需要按照實際長度進行初始化。
以下代碼是可以接受的:
AClass[] array = {object1, object2}
下面也是可以的:
AClass[] array = new AClass[2];...array[0] = object1;array[1] = object2;
但是這個不行:
AClass[] array;...array = {object1, object2};
請閱讀關於在 Java 軟體中如何初始化數組的討論。
接下來的內容現在我們已經討論了編譯器錯誤,下次我們將深入討論各種可能出現的運行時異常,這些異常會浪費你一整天時間。 就像本部分,它們將包含代碼塊、解釋和相關連結,以幫助您儘快修復代碼。
補充能量,回顧閱讀:
程式設計師應勤工資真有這麼高?編劇你可別騙我!
程式設計師!或將是未來最吃香的職業?
你知道為什麼程序中的缺陷叫bug嗎?
一個十二年老程序猿的碎碎念
(最新)各大公司Java後端開發面試題總結
Java初學者的30個常見問題
文章來源:開源翻譯