分享

50 个 Java 开发常见错误及规避技巧 (Part 1)

 半梦_Life 2017-07-11

在开发 Java 软件时可能会遇到许多类型的错误,但大多数可以避免。 我们列举了 50 个最常见的 Java 软件错误,其中包含代码示例和教程,以帮助您解决常见的编码问题。

如果您正在使用 .NET,您还应该查看我们的 50 个最常见的 .NET 软件错误指南,以及如何避免这些错误。 如果您当前的挑战与 Java 相关,请继续阅读以了解最常见的问题及其解决方法。


编译器错误


编译器错误消息在Java软件代码在编译器执行时产生。需要重点记住的是,一个编译器可能为一个错误抛出多个错误消息。所以修复第一个错误并重编译,就能修复很多的问题。


1. “… 可预料的”


当编码出现遗漏时,就会发生这类错误。可能是缺失了一个括号或者分号。

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


这种错误消息常常不会准确的定位到错误发生的位置。为了找到错误,建议:

  • 确保所有的左括号有对应匹配的右括号。

  • (使用 IDE,译者注)在代码行前的提示中检查。这种 Java 软件错误不要由编译器来关注,应该把更后面的工作交给它。

  • 有时候一个字符,比如一个左括号不应该写在 Java 代码的开始处。这样造成的结果是开发者不会写右括号去凑成一对。



2.“未封闭的 String 表达式”


“未封闭的 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 = new NFLPlayersReference [3];        nflplayersreference[0] = r;        players[1] = q;        nflplayers[2] = w;            for ( int i = 0; i <>'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. “非法的表达式开头” 


出现“非法表达式开头”错误的原因有很多。但它最终归类于一个不太有用的错误消息之一。有些开发者说这是由糟糕的代码造成的。


通常,创建表达式是用于生成新值或为变量赋值。编译器期望找到一个表达式,但找不到它,因为语法不符合预期。 在下面这些语句中可以找到此错误。


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


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


有几种方式会触发“无效的方法声明; 需求返回类型“错误:


  • 忘记说明返回类型

  • 如果方法没有返回值,那么需要用“void”表示方法签名中的返回类型。

  • 构造函数名称不需要说明返回类型。 但是,如果构造函数名称中出现错误,那么编译器会将构造函数视为没有指定类型的方法。


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


下面列举了一些编译器抛出“缺少返回语句”的消息的原因:

  • 返回语句被错误地省略了

  • 一个方法没有返回任何值,但是在方法签名中没有声明为void类型


10. “精度可能丢失”


当将超过一个变量可以保存的信息分配给该变量时,会发生“精度可能丢失”问题。如果发生这种情况,超出的信息将会被扔掉。如果这样做没问题,那么代码需要将变量显式地声明为新类型。


下面情况会发生“精度可能丢失”错误:


  • 将一个实数赋值给一个整型变量。

  • 将一个双精度浮点数赋值给一个整型变量。


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 }


代码编写工具和适当的代码缩进可以更容易地找到这些不对的大括号。


12. “语句不可达”


“语句不可达”发生在当语句被放在一个不会被执行的位置时候。通常是在 break 语句或 return 语句后面。


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


通常简单地移动 return 语句就能解决这个错误。


13. “变量 x 可能未被初始化”


这个问题发生在当方法内局部变量在声明时没有被初始化的时候。当一个变量未被初始化但是出现在 if 语句中的时候会发生该错误。


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


14. “操作符 ... 不能应用于 x”


这个情况发生于当操作符应用于没有定义其使用方法的类型上。


operator <>


当 Java 代码尝试使用 string 类型进行数学计算时会经常出现这个问题。为了解决它,string 需要被转化为 integer 或 float。


15. “不能转换的类型”


“不能转换的类型”错误发生在 Java 代码尝试进行非法转换的时候。


TypeInvocationConversionTest.java:12: inconvertible typesfound   : java.util.ArrayList<>>required: java.util.ArrayList<>>    lessRestrictiveClassList = (ArrayList<>>) 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++; //compiler error: non-static variable count cannot be referenced from a static context    }}


为了解决“非静态变量 ... 不能在静态上下文中被引用”的错误,有下述两种方法:

  • 在签名中将变量声明为静态变量。

  • 在静态方法中创建一个非静态对象的示例


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) Not Initialized” (数组未初始化)


当数组已声明但未初始化时,你将得到“(array)未初始化”的消息。 数组的长度是固定的,因此每个数组都需要按照实际长度进行初始化。

以下代码是可以接受的:


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个常见问题

文章来源:开源翻译

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多