原創(chuàng)|行業(yè)資訊|編輯:龔雪|2014-06-26 10:35:23.000|閱讀 273 次
概述:本文列舉了在Java程序開發(fā)中程序員最容易犯的10個(gè)錯(cuò)誤,期望對其他開發(fā)者有幫助。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
1、將數(shù)組轉(zhuǎn)化為列表
將數(shù)組轉(zhuǎn)化為一個(gè)列表時(shí),程序員們經(jīng)常這樣做:
List<String> list = Arrays.asList(arr);
Arrays.asList()會(huì)返回一個(gè)ArrayList對象,ArrayList類是Arrays的一個(gè)私有靜態(tài)類,而不是java.util.ArrayList類,java.util.Arrays.ArrayList類有set()、get()、contains()方法,但是沒有增加元素的方法,所以它的大小是固定的,想要?jiǎng)?chuàng)建一個(gè)真正的ArrayList類,你應(yīng)該這樣做:
ArrayList<String> arrayList =
new ArrayList<String>(Arrays.asList(arr));
ArrayList的構(gòu)造方法可以接受一個(gè)集合類型,剛好它也是java.util.Arrays.ArrayList的超類。
2、判斷一個(gè)數(shù)組是否包含一個(gè)值
程序員們經(jīng)常這樣做:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
這段代碼起作用,但是沒有必要把一個(gè)數(shù)組轉(zhuǎn)化成列表,轉(zhuǎn)化為列表需要額外的時(shí)間。它可以像下面那樣簡單:
Arrays.asList(arr).contains(targetValue);
或者是:
for(String s:arr){
if(s.equals(targetValue)){
return true;
}
}
return false;
第一種方法比第二種更容易讀
3、在一個(gè)循環(huán)中刪除一個(gè)列表中的元素
思考下面這一段在循環(huán)中刪除多個(gè)元素的的代碼
ArrayList<String> list =
new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println(list);
輸出結(jié)果是:
[b,d]
在這個(gè)方法中有一個(gè)嚴(yán)重的錯(cuò)誤。當(dāng)一個(gè)元素被刪除時(shí),列表的大小縮小并且下標(biāo)變化,所以當(dāng)你想要在一個(gè)循環(huán)中用下標(biāo)刪除多個(gè)元素的時(shí)候,它并不會(huì)正常的生效。
你也許知道在循環(huán)中正確的刪除多個(gè)元素的方法是使用迭代,并且你知道java中的foreach循環(huán)看起來像一個(gè)迭代器,但實(shí)際上并不是。考慮一下下面的代碼:
ArrayList<String> list =
new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
}
}
它會(huì)拋出一個(gè)ConcurrentModificationException異常。
相反下面的顯示正常:
ArrayList<String> list =
new ArrayList<String>(Arrays.asList("a","b","c","d"));
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
String s = iter.next();
if(s.equals("a")){
iter.remove();
}
}
.next()必須在.remove()之前調(diào)用。在一個(gè)foreach循環(huán)中,編譯器會(huì)使.next()在刪除元素之后被調(diào)用,因此就會(huì)拋出ConcurrentModificationException異常,你也許希望看一下ArrayList.iterator()的源代碼。
4、Hashtable與HashMap的對比
就算法而言,哈希表是數(shù)據(jù)結(jié)構(gòu)的一個(gè)名字。但是在java中,這個(gè)數(shù)據(jù)結(jié)構(gòu)的名字是HashMap。Hashtable與HashMap的一個(gè)重要不同點(diǎn)是Hashtable是同步的。所以你經(jīng)常不需要Hashtable,相反HashMap經(jīng)常會(huì)用到。
5、在集合中使用原始類型
在Java中原始類型與無界通配符類型很容易混合在一起,拿Set來說,Set是一個(gè)原始類型,而Set<?>是無界的通配符類型。
考慮下面使用原始類型List作為參數(shù)的代碼:
public static void add(List list,Object o){
list.add(o);
}
pulbic static void main(String[] args){
List<String> list = new ArrayList<String>();
add(list,10);
String s = list.get(0);
這段代碼會(huì)拋出一個(gè)異常:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
at ...
使用原生類型集合是危險(xiǎn)的,這是因?yàn)?原生類型集合跳過了泛型類型檢查,并且不是安全的,在Set、Set<?>和Set<Object>中有很大的不同。
6、訪問級(jí)別
程序員們經(jīng)常使用public作為類字段的修飾符,可以很簡單的通過引用得到值,但這是一個(gè)壞的設(shè)計(jì),按照經(jīng)驗(yàn),分配給成員變量的訪問級(jí)別應(yīng)該盡可能的低。
7、ArrayList與LinkedList的對比
當(dāng)程序員們不知道ArrayList與LinkedList的區(qū)別時(shí),他們經(jīng)常使用ArrayList,因?yàn)樗雌饋肀容^熟悉。然而,它們之前有巨大的性能差別。簡而言之,如果有大量的增加刪除操作并且沒有很多的隨機(jī)訪問元素的操作,應(yīng)該首先LinkedList。
8、可變與不可變
不可變對象有許多的優(yōu)點(diǎn),比如簡單,安全等等。但是對于每一個(gè)不同的值都需要一個(gè)獨(dú)立的對象,太多的對象可能會(huì)造成大量的垃圾回收。當(dāng)選擇可變與不可變時(shí)應(yīng)該有一個(gè)平衡。
一般的,可變對象用來避免產(chǎn)生大量的中間對象。一個(gè)典型的例子是連接大量的字符串。如果你用一個(gè)不可變的字符串,你會(huì)產(chǎn)生很多需要進(jìn)行垃圾回收的對象。這很浪費(fèi)CPU的時(shí)間,使用可變對象是正確的解決方案(比如StringBuilder)。
String result="";
for(String s: arr){
result = result + s;
}
有時(shí)在某些情況下也是需要可變對象的,比如將可變對象作為參數(shù)傳入方法,你不用使用很多語句便可以得到多個(gè)結(jié)果。另外一個(gè)例子是排序和過濾:當(dāng)然,你可以寫一個(gè)方法來接收原始的集合,并且返回一個(gè)排好序的集合,但是那樣對于大的集合就太浪費(fèi)了。(來自StackOverFlow的dasblinkenlight's的答案)
9、父類與子類的構(gòu)造函數(shù)
這個(gè)編譯期錯(cuò)誤的出現(xiàn)是父類默認(rèn)的構(gòu)造方法未定義,在java中,如果一個(gè)類沒有定義構(gòu)造方法,編譯器會(huì)默認(rèn)的為這個(gè)類添加一個(gè)無參的構(gòu)造方法。如果在父類中定義了構(gòu)造方法,在這個(gè)例子中是Super(String s),編譯器就不會(huì)添加默認(rèn)的無參構(gòu)造方法,這就是上面這個(gè)父類的情形。
子類的構(gòu)造器,不管是無參還有有參,都會(huì)調(diào)用父類的無參構(gòu)造器。因?yàn)榫幾g器試圖在子類的兩個(gè)構(gòu)造方法中添加super()方法。但是父類默認(rèn)的構(gòu)造方法未定義,編譯器就會(huì)報(bào)出這個(gè)錯(cuò)誤信息。
想要修復(fù)這個(gè)問題,可以簡單的通過1)在父類中添加一個(gè)Super()構(gòu)造方法,像下面這樣:
public Super(){
System.out.println("Super");
}
或者2)移除父類自定義的構(gòu)造方法,或者3)在子類的構(gòu)造方法中調(diào)用父類的super(value)方法。
10、還是構(gòu)造器
有兩種方式可以創(chuàng)建字符串
//1.使用字符串
String x = "abc";
//2.使用構(gòu)造器
String y = new String("abc");
有什么區(qū)別?
下面的例子會(huì)給出一個(gè)快速的答案:
String a = "abc";
String b = "abc";
System.out.println(a==b);//true
System.out.println(a.equals(b));//true
String c = new String("abc");
String d = new String("abc");
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn