原文:50 Common Java Errors and How to Avoid Them (Part 1)
作者:Angela Stringfellow
翻译:雁惊寒
译者注:本文介绍了20个常见的Java编译器错误,每种错误都包含了代码片段、问题说明,并给出了相关的链接来帮助你快速地理解并解决这些问题。以下是译文。
在开发Java软件的时候可能会遇到很多类型的错误,但大多数可以避免。我们精心挑选了20个最常见的Java软件错误,包含了代码示例和教程,以帮助你解决一些常见的编码问题。
要获得更多编写Java程序的提示和技巧,你可以下载我们的“Comprehensive Java Developer’s Guide”这本书,它里面包含了所有你需要的东西,从各类工具到最佳网站和博客、YouTube频道、Twitter影响者、LinkedIn组、播客、must-attend events等等。
如果你正在使用.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;
}
通常,这种错误消息不会指出产生问题的确切位置。要找出问题所在,需要:
实例:一个丢失的圆括号引发的错误。
当字符串结尾缺少引号时,会产生“unclosed string 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");
}
}
通常,这种错误在以下这些情况下会产生:
请阅读这篇文章:未封闭的字符串错误消息。
出现“Illegal Start of an Expression”错误的原因有很多。它已经成为不太有用的错误消息之一。一些开发者认为这是由坏的代码味道造成的。
通常,创建一个表达式是为了生成一个新值或给其他变量赋值。编译器期望找到一个表达式,但是因为语法不符合预期而找不到表达式。在下面这些代码中可以找到这种错误。
} // 把它添加到这里
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.");
}
}
} // 从这里删掉它
}
请阅读这篇文章:如何排除“illegal start of an expression”错误。
这是一个非常常见的问题,因为Java中的所有标识符都需要在使用之前进行声明。出现这个错误是因为,在编译代码时,编译器不明白该标识符的含义。
有很多原因可能会产生“cannot find symbol”错误信息:
请阅读这篇文章:关于“cannot find symbol”错误的讨论。
当XXX类和Java程序文件名不匹配时,就会产生“public class XXX should be in file”错误消息。 只有当类名和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);
}
}
要解决这个问题,可以:
请阅读这篇文章:“Public class XXX should be in file”错误的示例。
“Incompatible Types”是赋值语句尝试对变量与表达式进行类型匹配时发生的逻辑错误。通常,将字符串赋值给一个整数时会产生这个错误,反之亦然。这不是一个Java语法错误。
test.java:78: error: incompatible types
return stringBuilder.toString();
^
required: int
found: String
1 error
当编译器抛出“incompatible types”消息时,确实不太容易解决这个问题:
看一下这个例子:将一个字符串赋值给整数会出现“incompatible types”错误。
这个错误消息的意思是,在方法声明中未显示地声明方法的返回类型。
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”错误:
看一个这个例子:构造函数的命名问题触发“invalid method declaration; return type required“问题。
这个错误消息比较有用,它的意思是某个方法调用了错误的参数。
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错误。
当一个方法缺少return语句时,会触发“Missing Return Statement”错误消息。有返回值(非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!");
}
}
编译器抛出“missing return statement”消息有这几个原因:
请查看如何解决“missing return statement”错误这个例子。
当赋值给变量的信息超过了该变量可以承载的上限时,就会触发“Possible Loss of Precision”错误。一旦发生这种情况,部分信息将被丢弃。如果这样做没问题的话,那么在代码上应该将变量显式地声明为新的类型。
以下情况通常会发生“possible loss of precision”错误:
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 }
编码工具和适当的代码缩进可以更容易地找到这些不匹配的大括号。
请阅读这篇文章:缺少的大括号会触发“reached end of file while parsing”错误消息。
当一条语句出现在一个它不可能被执行的地方时,会触发“Unreachable statement”错误。通常,是在一个break或return语句之后。
for(;;){
break;
... // unreachable statement
}
int i=1;
if(i==1)
...
else
... // dead code
通常,简单地移动return语句即可修复此错误。请阅读这篇文章:如何修复“Unreachable Statement”错误。
在方法中声明的局部变量如果没有初始化,就会发生这种错误。如果在if语句中包含没有初始值的变量时,就会发生这种错误。
int x;
if (condition) {
x = 5;
}
System.out.println(x); // x可能尚未初始化
请阅读这篇文章:如何避免触发“Variable Might Not Have Been Initialized”错误。
当操作符作用于未在其定义范围内的类型时,会出现此问题。
operator < cannot be applied to java.lang.Object,java.lang.Object
当Java代码尝试在计算(减法、乘法、大小比较等)中使用字符串类型时,经常会触发这种错误。要修复这个问题,需要将字符串转换为整数或浮点数。
请阅读这篇文章:非数字类型为什么会导致Java软件错误。
当Java代码尝试执行非法转换时,会发生“Inconvertible Types”错误。
TypeInvocationConversionTest.java:12: inconvertible types
found : java.util.ArrayList.lang.Class extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList.lang.Class>>
lessRestrictiveClassList = (ArrayList>) classList;
^
例如,布尔类型不能转换为整形。
请阅读这篇文章:如何在Java软件中转换不可转换的类型。
当返回语句包含不正确的类型时,你会收到“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”错误。
当一个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;
}
请阅读这篇文章:如何修复“Cannot Return a Value From Method Whose Result Type Is Void”错误。
当编译器尝试在静态方法中访问非静态变量时,会发生此错误:
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
}
}
要解决“Non-Static Variable … Cannot Be Referenced From a Static Context”这个错误,可以做两件事情:
请阅读这个教程:静态和非静态变量之间的区别。
当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
要在静态方法中调用非静态方法,需要是声明一个要调用的非静态方法的类的实例。
请阅读这篇文章:非静态方法和静态方法之间的区别。
当数组已经声明但未初始化时,你会得到“(array) Not Initialized”这样的错误消息。数组的长度是固定的,因此每个数组都需要以所需的长度进行初始化。
以下代码是正确的:
AClass[] array = {object1, object2}
这样也可以:
AClass[] array = new AClass[2];
...
array[0] = object1;
array[1] = object2;
但这样是不正确的:
AClass[] array;
...
array = {object1, object2};
请阅读这篇文章:关于如何在Java中初始化数组。
今天我们讨论了编译器的错误,下次我们将深入讨论各种可能会出现的运行时异常。像本文的结构一样,下次也会包含代码片段、解释,以及相关的链接来帮助你尽快修复代码。