java學習:你知道嗎?Java常見的幾大程式碼
1、在靜態方法中訪問非靜態的成員變數(例如在main方法中)
有很多剛剛接觸Java的程式遠都會有一問題,就是在main方法中訪問成員變數。Main方法一般都被標示為“靜態的”,意思就是我們不需要例項化這個類來呼叫main方法。例如,java虛擬機器能夠以這樣的形式來呼叫MyApplication類:
MyApplication.main(命令列引數);
這裡並沒有例項化MyApplication類,或者這裡沒有訪問任何的成員變數。例如下面的程式就會產生一個編譯器的錯誤。
public class StaticDemo
{
public String my_member_vaiable = "somedata";
public static void main (String args[])
{
// Access a non-satic member from static method
System.out.println ("This generates a compiler error"+
my_member_variable);
}
}
如果你要訪問一個靜態方法中的成員變數(比如main方法),你就需要例項化一個物件。下面這段程式碼示例瞭如何正確的訪問一個非靜態的成員變數。其方法就是首先例項化一個物件。
小編是一個有著5年工作經驗的java程式設計師,對於java,自己有做資料的整合,一個完整學習java的路線,學習資料和工具,相信這裡有很多學習java的小夥伴,我創立了一個2000人學習扣群,479121291。無論是初級還是進階的小夥伴小編我都歡迎!
public class NonStaticDemo
{
public String my_member_variable = "somedata";
public static void main (String args[])
{
NonStaticDemo demo = new NonStaticDemo();
// Access member variable of demo
System.out.println ("This WON'T generate an error"+
demo.my_member_variable);
}
}
2、在過載的時候錯誤的鍵入方法名過載允許程式設計師用新的程式碼去覆蓋方法的實現
過載是一個便利的特性,很多面對物件的程式設計師都在大量的使用它。如果你使用AWT1.1的時間處理模型,你通常會覆蓋listener方法去實現定製的功能。一個在過載方法的時候很容易犯的錯誤就是錯誤的鍵入要過載的方法名。如果你錯誤的輸入了方法名,你就不是在過載這個方法了。相反的,你是在重新定義一個方法,只不過這個方法的引數和返回型別和你要過載的方法相同罷了。
public class MyWindowListener extends WindowAdapter {
// This should be WindowClosed
public void WindowClose(WindowEvent e) {
// Exit when user closes window
System.exit(0);
}
}
這個方法不會通過編譯,很容易就能捕捉找它。在過去我曾經注意過一個方法,並且相信它是被呼叫的,花了很多時間去找這個錯誤。這個錯誤的表現就是你的方法不會被呼叫,你以為你的方法已經被跳過了。一種可行的解決方法就是增加一條列印輸出語句。在日誌檔案中記錄下資訊。或者是使用跟蹤除錯程式(例如VJ++或者是Borland JBuilder)來一行一行的除錯。如果你的方法還不能被呼叫,那很可能就是你的方法名鍵入錯誤了。
3、比較和分配(“=”強於“==”)
當我們使用==運算子的時候,我們實際上是在比較兩個物件的引用,來看看他們是不是指向的同一個物件。舉個例子,我們不能使用==運算子來比較兩個字串是否相等。我們應該使用。equals方法來比較兩個物件,這個方法是所有類共有的,它繼承自java.lang.Object。
下面是比較兩個字串相等的正確的方法:
// Bad way
if( (abc + def) == "abcdef" )
{
……
}
// Good way
if ( (abc + def)。equals("abcdef") )
{
……
}
4、混淆值傳遞和引用傳遞
這是一個不太容易發現的錯誤。因為,當你看程式碼的時候,你會十分確定這是一個引用傳遞,而它實際上卻是一個值傳遞。Java這兩者都會使用,所以你要理解你什麼時候需要值傳遞,什麼時候需要引用傳遞。當你要傳遞一個簡單的資料型別到一個函式中,比如,char、int、float或者double,你是在傳遞一個值。這個意味著這種資料型別的被複制了一個拷貝,是這個拷貝被傳遞到了函式中。如果這個函式去修改這個值,僅僅是這個值的拷貝被修改了。這個函式結束以後,將會返回到控制呼叫函式去,這時候那個“真正的”值沒有收到影響,沒有任何改變被儲存。
如果你想修改一個簡單的資料型別,可以將這個資料型別定位一個返回值或者將它封裝到一個物件中。
當你要傳遞一個java物件到一個函式中,比如,陣列、向量或者是一個字串,此時你傳遞的就是一個物件的引用。這裡的字串也是一個物件,而不是一個簡單資料型別。這就意味著你要傳遞一個物件到一個函式,你就要傳遞這個物件的引用,而不能去複製它。任何對這個物件的成員變數的改變都會持久化,這種改變的好壞要取決於你是否是刻意而為之。
有一點要注意,如果字串沒有包含任何方法改變它的值的時候,你最好將它作為值來傳遞。
5、寫一個空的異常處理
我知道一個空的異常處理就像忽略錯誤一樣很誘人。但是如果真的發生了錯誤,你不會得到一個錯誤資訊的輸出,它使得不太可能發現錯誤的原因。甚至是最簡單的一場處理都是很有用處的。舉個例子,在你的程式碼加上try{}catch{},去試著捕捉任何的一場丟擲,並打印出錯誤資訊。你不用為每個異常都寫出定製的處理(雖然這是一個很好的程式設計習慣)。但是不要將這個異常處理空著,否則你就不會知道有什麼錯誤發生了。
舉例:
public static void main(String args[])
{
try{
// Your code goes here
}
catch (Exception e)
{
System.out.println ("Err - " + e );
}
}
6、忘記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.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));
}
}
7、防止執行緒在共享變數中並行存取
在寫一個多執行緒的應用程式的時候,許多程式設計師都喜歡抄近路。而這樣會是他們的應用程式或者是小應用程式發生執行緒衝突。當兩個或者兩個以上的執行緒訪問同一個資料的時候,就存在一定的概率(概率大小取決於墨菲法則)使得兩個執行緒同時的訪問或者修改同一個資料。不要愚蠢的認為這樣的情況不會發生在單執行緒的應用程式中。當訪問同一個資料的時候,你的執行緒就很可能被掛起,而第二個執行緒進入時就會覆蓋第一個執行緒修改的地方。
這樣的問題不是僅僅出現在多執行緒應用程式或者是小應用程式中的。如果你寫了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;
}
}
8、大寫錯誤
這是一個我們最經常犯的錯誤。他是很簡單的,但是有時我們看著一個沒有大寫的變數或者方法卻並不能發現這個錯誤。我自己也常常感到困惑,因為我認為這些方法和變數都是存在的,但是卻發現不了他們沒有大寫。
這裡你不能用銀子彈來檢查它,你只能自己訓練者來減少這種錯誤。這裡有個竅門:
Java api中所用的方法和變數名都應該以小寫字母來開頭。
所有的變數名和方法名的新詞的開頭都要用大寫字母。
如果你以這樣的形式來定義你的變數名和類名,你就是在有意識的使他們走向正確,你就能逐漸的減少這樣的錯誤的數量。這可能需要一段時間,但是在以後有可能會避免更為嚴重的錯誤。
下來就是java程式設計師最常犯的錯誤了!!!
9、空指標
空指標是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];
}
// Chexk all the parameters
for (int i = 0; i < list.length; i++)
{
if (list[i].equals"-help")
{
//……
}
//else……
}
}
上面的程式碼(作為認為的例子),顯示了通常的錯誤。在某些情況下,使用者輸入了三個或者更多的引數,上述程式碼將會正常執行。但是如果沒有引數被輸入,那麼在執行的時候就會得到一個空指標異常。某些時候你的變數將會被初始化,但是其他時候他們卻不會。一個簡單的解決辦法就是在你的訪問陣列元素的時候先檢查它十分為空。
總結
以上整理的這些錯誤是Java開發者常犯的一下錯誤,雖說在編碼的時候不可能完全的避免錯誤,但是你應該去避免犯一些重複的錯誤。