50個常見的 Java 錯誤及避免方法(第一部分)

2017-09-20    分類:JAVA開發、程式設計開發、首頁精華0人評論發表於2017-09-20

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

在開發Java軟體時可能會遇到許多型別的錯誤,但大多數是可以避免的。為此我們羅列了50個最常見的Java編碼錯誤,其中包含程式碼示例和教程,以幫助大家解決常見的編碼問題。

編譯器錯誤

當Java軟體程式碼通過編譯器執行時,會建立編譯器錯誤訊息。謹記編譯器可能會針對一個錯誤丟擲許多錯誤訊息。所以得修復第一個錯誤並重新編譯。這樣做可以解決很多問題。

1.“…Expected”

當程式碼中缺少某些東西時,會發生此錯誤。通常是因為缺少分號或右括號。

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

通常,此錯誤訊息不會精確確定問題的確切位置。為了找到錯誤:

  • 確保所有的左括號都有一個對應的右括號。
  • 在檢視指示的Java程式碼行之前順便看看行。此Java軟體錯誤沒有被編譯器注意到,直到在程式碼中更深層次地檢視。
  • 有時一個字元,如一個左括號,並不應該放在Java程式碼的原先位置。所以開發人員沒有放置一個右括號來平衡括號。

點選檢視關於錯誤的圓括號會如何導致錯誤(@StackOverflow)的示例

2.“Unclosed String Literal”

如果字串文字結束時沒有引號的話,會建立“Unclosed String Literal”的錯誤訊息,並且訊息將顯示在與錯誤相同的行上。(@DreamInCode)Literal是值的原始碼。

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 = new NFLPlayersReference [3];
        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");
    }     
}

通常。這種情況發生在:

  • 字串文字不以引號結尾。這很容易糾正,加上所需的引號,閉合字串文字即可。
  • 字串文字擴充套件超過一行。長字串文字可以分解成字串文字,並加上加號(“+”)。
  • 作為字串文字一部分的引號不通過反斜槓(“\”)進行轉義。

點選閱讀關於Java軟體錯誤訊息Unclosed String Literal的討論。(@Quora)

3.“Illegal Start of an Expression”

出現“Illegal Start of an Expression”錯誤的原因有很多。因此名列不太有用的錯誤訊息之一。有些開發者甚至認為這是由壞的程式碼造成的。

通常,建立表示式是為了生成新的值或為變數分配值。編譯器期望找到表示式,但因為語法不符合預期而找不到表示式。(@StackOverflow)在這些語句中就可以發現此錯誤。

} // ADD IT HERE
       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.");
        }
        }
    } // REMOVE IT FROM HERE
    }

點選瀏覽關於如何排除“Illegal Start of an Expression”錯誤的討論。(@StackOverflow)

4.“Cannot Find Symbol”

這是一個非常常見的問題,因為Java中的所有識別符號都需要在被使用之前進行宣告。 發生錯誤的原因在於編譯程式碼時,編譯器不明白識別符號的含義。

可能收到“Cannot Find Symbol”資訊的原因有很多:

  • 識別符號宣告時的拼寫可能與在程式碼中使用時的拼寫不同。
  • 變數從未被宣告。
  • 變數使用時與宣告未在同一範圍內。
  • 類沒有匯入。

點選閱讀有關“Cannot Find Symbol”錯誤的詳細討論以及產生此問題的程式碼示例。(@StackOverflow)

5.“Public Class XXX Should Be in File”

當XXX類和Java程式檔名不匹配時,會發生“Public Class XXX Should Be in File”訊息。只有當類和Java檔案相同時,程式碼才會被編譯。(@coderanch):

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

為解決這個問題:

  • 類和檔案命名相同。
  • 確保兩名稱的情況一致。

點選查閱“Public Class XXX Should Be in File”錯誤的示例。(@StackOverflow)

6.“Incompatible Types”

“Incompatible Types”是指定語句嘗試將變數與型別表示式配對時發生的邏輯錯誤。 通常會在程式碼嘗試將文字字串放入到整型中時出現,反之亦然。這並非Java語法錯誤。(@StackOverflow)

test.java:78: error: incompatible types
return stringBuilder.toString();
                             ^
required: int
found:    String
1 error

當編譯器給出“Incompatible Types”訊息時,就不是簡單修復可以擺平的了:

  • 有可以轉換型別的函式。
  • 開發人員可能需要更改程式碼預期的功能。

檢視此例子,裡面說明了如何試著將一個字串分配給一個整數,出現“Incompatible Types”訊息。(@StackOverflow)

7.“Invalid Method Declaration; Return Type Required”

此Java軟體錯誤訊息表示方法簽名中未明確宣告方法的返回型別。

public class Circle
{
    private double radius;
    public CircleR(double r)
    {
        radius = r;
    }
    public diameter()
    {
       double d = radius * 2;
       return d;
    }
}

有若干途徑會觸發“Invalid Method Declaration; Return Type Required” 錯誤:

  • 忘記宣告型別
  • 如果方法沒有返回值,那麼需要將“void”宣告為方法簽名中的型別。
  • 建構函式名稱不需要宣告型別。 但是,如果建構函式名稱中存在錯誤,那麼編譯器將會把建構函式視為沒有指定型別的方法。

檢視此說明建構函式命名如何觸發“Invalid Method Declaration; Return Type Required” 問題的例子。(@StackOverflow)

8.“Method <X> in Class <Y> Cannot Be Applied to Given Types”

此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

呼叫的方法期待方法宣告中定義的某些引數。檢查方法宣告並仔細呼叫,以確保它們是相容的。

檢視此討論,裡面說明了Java軟體錯誤訊息如何識別在方法宣告和方法呼叫中由引數建立的不相容性。(@StackOverflow)

9.“Missing Return Statement”

當一個方法沒有返回語句時,就會出現“Missing Return Statement”的訊息。每個返回值(非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!");
    }
}

編譯器丟擲“Missing Return Statement”訊息的原因有若干:

  • 返回語句由於錯誤被省略。
  • 該方法沒有返回任何值,但型別void在方法簽名中未宣告。

檢視如何修復“Missing Return Statement”Java軟體錯誤的示例。(@StackOverflow)

10.“Possible Loss of Precision”

當更多的資訊被分配給一個變數而超過它的容量,就會發生“Possible Loss of Precision”訊息。如果出現這種情況,那麼碎片就會被扔掉。 如果這樣沒有關係,那麼程式碼需要將變數顯式宣告為新的型別。

“Possible Loss of Precision”錯誤通常發生在:

  • 嘗試為整數資料型別的變數分配一個實數。
  • 嘗試為整數資料型別的變數分配一個double。

Java中基本資料型別的解釋表述了資料特徵。(@Oracle)

11.“Reached End of File While Parsing”

當程式缺少關閉大括號(“}”)時,Java程式碼中就會發生此錯誤訊息。 有時我們可以通過在程式碼的末尾放置大括號來快速修復錯誤。

public class mod_MyMod extends BaseMod
public 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 }

編寫utilities程式和適當的程式碼縮排可以更容易地找到這類遺漏的大括號。

示例表述了缺少了大括號會如何建立“Reached End of File While Parsing”的錯誤訊息。(@StackOverflow)

12.“Unreachable Statement”

當一個語句寫在一個阻止它執行的地方時,就會發生“Unreachable statement”錯誤。通常它出現在中斷或返回語句之後。

for(;;){
   break;
   ... // unreachable statement
}
int i=1;
if(i==1)
  ...
else
  ... // dead code

通常簡單地移動返回語句將修復錯誤。閱讀關於如何修復Unreachable Statement Java軟體錯誤的討論。 (@StackOverflow)

13.“Variable <X> Might Not Have Been Initialized”

當方法中宣告的區域性變數未初始化時,就會發生這種錯誤。它也會出現在沒有初始值的變數是if語句組成部分的情況下。

int x;
if (condition) {
    x = 5;
}
System.out.println(x); // x may not have been initialized

閱讀此關於如何避免觸發“Variable <X> Might Not Have Been Initialized”錯誤的討論。(@reddit)

14.“Operator … Cannot be Applied to <X>”

當操作符用於非定義中的型別時,就會出現此問題。

operator < cannot be applied to java.lang.Object,java.lang.Object

當Java程式碼嘗試在計算中使用型別字串時,通常會發生這種情況。 要修復的話,就需要將字串轉換為整型或浮點型。

閱讀此說明非數字型別如何導致Java軟體錯誤從而警報操作符無法應用於型別的例子。 (@StackOverflow)

15.“Inconvertible Types”

當Java程式碼嘗試執行非法轉換時,就會發生“Inconvertible Types”錯誤。

TypeInvocationConversionTest.java:12: inconvertible types
found   : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList<java.lang.Class<?>>
    lessRestrictiveClassList = (ArrayList<Class<?>>) classList;

例如,布林值不能轉換為整型。

閱讀此關於如何在Java軟體中轉換不可轉換的型別的討論。(@StackOverflow)

16.“Missing Return Value”

當return語句包含不正確的型別時,你將收到“Missing Return Value”的訊息。例如,以下程式碼:

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

通常,有一個返回語句不返回任何東西。

閱讀此關於如何避免“Missing Return Value”Java軟體錯誤訊息的討論。(@coderanch)

第一部分完,敬請關注第二部分的內容。

譯文連結:http://www.codeceo.com/article/50-java-errors-part-1.html
英文原文:50 Common Java Errors and How to Avoid Them (Part 1)
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章