6、写一个空的异常处理
我知道一个空的异常处理就像忽略错误一样很诱人。但是如果真的发生了错误,你不会得到一个错误信息的输出,它使得不太可能发现错误的原因。甚至是最简单的异常处理都是很有用处的。举个例子,在你的代码加上try{}catch{},去试着捕捉任何的异常抛出,并打印出错误信息。你不用为每个异常都写出定制的处理(虽然这是一个很好的编程习惯)。但是不要将这个异常处理空着,否则你就不会知道有什么错误发生了。
举例:
public
static
void main(String args[])
...{
try
...{
// Your code goes here
}
catch (Exception e)
...{
System.out.println ("Err - "
+ e );
}
}
7、忘记java中索引是从0开始的
如果你有C/C++的编程背景的话,你在使用其他编程语言的时候就不会发现同样的问题了。
在java中数组的索引是从0开始的,这就是说第一个元素的索引必须是0.困惑了?让我们看看例子吧。
// Create an array of three strings
String[] strArray =
new String[3];
// First element's index is actually 0
strArray[0] =
"First string";
// Second element's index is actually 1
strArray[1] =
"Second string";
// Final element's index is actually 2
strArray[2] =
"Third and final string";
在这个例子中,我们定义了一个有着三个字符串的数组,当我们访问它的元素时候减去了一个。现在,当我们试着去访问strArray[3],也就是第四个元素的时候,就会有一个ArrayOutOfBoundsException异常被抛出。这个就是最明显的例子-忘记了0索引规则。
在其他地方0索引规则也能使你陷入麻烦。例如字符串中。假设你要从一个字符串确定的偏移位置处得到一个字符,使用String.charAt(int)函数,你就能看到这个信息。但是在java中,字符串类的索引也是从0开始的,这就是说第一个字符的偏移位置为0,第二个为1.你可能会陷入一些麻烦,如果你不注意这个问题的话,特别是你的应用程序中使用了大量的字符串处理程序,那样的话你就很可能使用错误的字符,同时在运行是抛出一个StringIndexOutOfBoundsException异常,就像ArrayOutOfBoundsException异常一样。下面的例子证明了这些:
public
class StrDemo
...{
public
static
void main (String args[])
...{
String abc =
"abc";
System.out.println ("Char at offset 0 : "
+ abc.charAt(0) );
System.out.println ("Char at offset 1 : "
+ abc.charAt(1) );
System.out.println ("Char at offset 2 : "
+ abc.charAt(2) );
// This line should throw a StringIndexOutOfBoundsException
System.out.println ("Char at offset 3 : "
+ abc.charAt(3) );
}
}
同时应该注意的是,0索引规则不应该只应用在数组或是字符串中,java的其他部分也会用到。但是并不是全部都会用到。Java.util.Date和java.util.Calendar,这两个类的月份都是从0开始的,但是日期却通常是从1开始的,下面的程序证明了这一点。
import java.util.Date;
import java.util.Calendar;
public
class ZeroIndexedDate
...{
public
static
void main (String args[])
...{
// Get today's date
Date today =
new Date();
// Print return value of getMonth
System.out.println ("Date.getMonth() returns : "
+
today.getMonth());
// Get today's date using a Calendar
Calendar rightNow = Calendar.getInstance();
// Print return value of get ( Calendar.MONTH )
System.out.println ("Calendar.get (month) returns : "
+
rightNow.get ( Calendar.MONTH ));
}
}
8、防止线程在共享变量中并行存取
在写一个多线程的应用程序的时候,许多程序员都喜欢抄近路。而这样会是他们的应用程序或者是小应用程序发生线程冲突。当两个或者两个以上的线程访问同一个数据的时候,就存在一定的概率(概率大小取决与墨菲法则)使得两个线程同时的访问或者修改同一个数据。不要愚蠢的认为这样的情况不会发生在单线程的应用程序中。当访问同一个数据的时候,你的线程就很可能被挂起,而第二个线程进入是就会覆盖第一个线程修改的地方。
这样的问题不是仅仅出现在多线程应用程序或者是小应用程序中的。如果你写了java api或者是java bean,你的代码就很可能不是线程安全的。即使你从来没有写过一个使用线程的单独的应用程序,人们也有可能使用你的程序。为了其他人,不仅仅是你,你就应该采取措施防止线程在共享变量中并行存取。
怎样来解决这个问题呢,最简单的就是让你的变量私有化。同时使用同步存取方法。存取方法允许访问似有的成员变量,但是仅仅是在一种控制方式中。下面的存取方法就能够以安全的方式修改计数器的值。
public
class MyCounter
...{
private
int count =
0; // count starts at zero
public
synchronized
void setCount(int amount)
...{
count = amount;
}
public
synchronized
int getCount()
...{
return count;
}
}
9、大写错误
这是一个我们最经常犯的错误。它是很简单的,但是有时我们看着一个没有大写的变量或者方法却并不能发现这个错误。我自己也常常感到困惑,因为我认为这些方法和变量都是存在的,但是却发现不了他们没有大写。
这里你不能用银子弹来检查它,你只能自己训练着来减少这种错误。这里有一个窍门:
Java api中所用的方法和变量名都应该以小写字母来开头。
所有的变量名和方法名的新词的开头都要用大写字母。
如果你以这样的形式来定义你的变量名和类名,你就是在有意识的使它们走向正确,你就能逐渐的减少这样错误的数量。这可能需要一段时间,但是在以后有可能会避免更为严重的错误。
下来就是java程序员最常犯的错误了!!!
10、空指针
空指针是java程序员最经常犯的错误了。编译器不会为你检查出这个错误它仅仅在运行时在表现出来,如果你发现不了它,你的用户将很可能发现它。
当试着访问一个对象的时候,这个对象的引用就是空的,一个NullPointerException异常就会被抛出。空指针错误的原因是多种多样的,但是一般情况下发生这种错误意味着你没有对一个对象初始化,或者是你没有检查一个函数的返回值。
许多函数返回一个空是用来指示一个错误的条件被执行。如果你不检查返回值的话,你由于不可能知道发生了什么。既然原因是一个错误的条件,一般的测试就不会发现它,这就意味着你的用户可能在最后的时候替你发现它。如果API函数指明一个空的对象很可能被返回,那在使用对象的引用之前一定要进行检查。
另外的原因可能是你在初始化对象的时候不规范,或者是它的初始化是有条件的。举例,检查下面的代码,看看你是否能发现这个错误。
public
static
void main(String args[])
...{
// Accept up to 3 parameters
String[] list =
new String[3];
int index =
0;
while ( (index < args.length) && ( index <
3 ) )
...{
list[index++] = args[index];
}
// Check all the parameters
for (int i =
0; i < list.length; i++)
...{
if (list.equals "-help")
...{
// ……
}
else
if (list.equals "-cp")
...{
// ……
}
// else ……
}
}
上面的代码(作为人为的例子),显示了通常的错误。在某些情况下,用户输入了三个或者更多的参数,上述代码将会正常运行。但是如果没有参数被输入,那么在运行的时候就会得到一个空指针异常。某些时候你的变量将会被初始化,但是其他时候它们却不会。一个简单的解决办法就是在你访问数组元素的时候先检查它是否为空。 |