摘要:原文出自本文總結(jié)了程序員常犯的個錯誤??梢钥纯礊槭裁丛谥斜辉O(shè)計(jì)成不可變父類和子類的構(gòu)造函數(shù)以上這段代碼出現(xiàn)編譯錯誤,因?yàn)槟J(rèn)的父類構(gòu)造函數(shù)未定義。如果程序員定義構(gòu)造函數(shù),編譯器將不插入默認(rèn)的無參數(shù)構(gòu)造函數(shù)。
原文出自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/
本文總結(jié)了Java程序員常犯的10個錯誤。
1. 把Array轉(zhuǎn)化成ArrayList把Array轉(zhuǎn)化成ArrayList,程序員經(jīng)常用以下方法:
List
Arrays.asList() 實(shí)際上返回一個ArrayList,但是這個ArrayList是Arrays的一個內(nèi)部私有類,而不是java.util.ArrayList類。這個私有類java.util.Arrays.ArrayList有set(), get(), contains()方法,但是不能夠添加新的元素。它的大小是固定的。如果你想要一個java.util.ArrayList,正確的方法是:
ArrayList
java.util.ArrayList的構(gòu)造函數(shù)可以接受一個集合類型。java.util.Arrays.ArrayList也繼承了集合類型,所以可以作用參數(shù)使用。
開發(fā)人員經(jīng)常做的是:
Set
return set.contains(targetValue);
這個代碼是工作的,但沒有沒有效率。把列表轉(zhuǎn)換成set沒有必要,需要額外的時間。正確的方法是:
Arrays.asList(arr).contains(targetValue);
或者,一個簡單的loop:
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
第一種比第二種更具有可讀性。
考慮下面的代碼,迭代過程中刪除元素:
ArrayList
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
System.out.println(list);
這段代碼的輸出是:
[b, d]
這個方法有一個嚴(yán)重的問題。當(dāng)元素被移除,該列表的大小縮減,元素索引也隨之發(fā)生了變化。所以,如果你想通過使用索引來刪除一個循環(huán)內(nèi)的多個元素,就會導(dǎo)致錯誤的結(jié)果。
你可能猜到可以使用iterator來刪除循環(huán)中的元素。在Java中的foreach循環(huán)的工作原理就像一個iterator。 但是在這里也會發(fā)生錯誤。請看下面的代碼:
ArrayList
for (String s : list) {
if (s.equals("a"))
list.remove(s);
}
上面的foreach loop代碼會拋出一個異常ConcurrentModificationException. 但是下面這段代碼不會。
ArrayList
Iterator
while (iter.hasNext()) {
String s = iter.next();
if (s.equals("a")) { iter.remove(); }
}
通過分析ArrayList.iterator()的原代碼,我們可以發(fā)現(xiàn)next()方法必須要在remove()方法前被調(diào)用。在foreach loop中,編譯器產(chǎn)生的代碼會先調(diào)用next()方法,從而產(chǎn)生異常ConcurrentModificationException。請查看ArrayList.iterator()的原代碼。
按照算法慣例,Hashtable是數(shù)據(jù)結(jié)構(gòu)的名稱。但在Java中,數(shù)據(jù)結(jié)構(gòu)的名稱是HashMap。Hashtable是同步的版本。所以很多時候你并不需要Hashtable,而是HashMap。 這兩篇文章詳細(xì)介紹了各種Map的區(qū)別和常見的問題: HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap, Map常見10大問題,
5.使用原始類型Collection在Java中,原始類型和無界通配符類型很容易混在一起。以Set為例,Set是原始類型,而Set>是無界通配符類型。
考慮下面的代碼,它使用原始類型的List作為參數(shù):
public static void add(List list, Object o){
list.add(o);
}
public static void main(String[] args){
List
很多時候,開發(fā)者使用public修飾字段。這樣做的好處是很容易通過直接引用來獲取字段的值,但是這是一個非常糟糕的設(shè)計(jì)。經(jīng)驗(yàn)法則是“給成員的訪問級別盡可能低”。可以查看Java4種不同的訪問級別public, default, protected, and private。
7. ArrayList 與 LinkedList當(dāng)開發(fā)人員不知道ArrayList和LinkedList的區(qū)別的時候,他們經(jīng)常使用的是ArrayList,可能因?yàn)樗雌饋砻媸?。但是ArrayList和LinkedList之間有巨大的性能差異。 簡單來說如果有大量的添加/刪除操作,而沒有很多隨機(jī)存取操作,LinkedList的應(yīng)該是首選??梢圆榭碅rrayList與LinkedList了解它們之間更多的區(qū)別。
8.可變性與不變性不可變對象有很多優(yōu)點(diǎn),如簡單性,安全性等。但是它需要為每個不同的值創(chuàng)造一個多帶帶的對象,對象太多可能會導(dǎo)致垃圾回收的成本高。所以可變和不可變之間進(jìn)行選擇時應(yīng)該有一個平衡。
一般情況下,使用可變對象,以避免產(chǎn)生過多的中間對象。一個經(jīng)典的例子是串聯(lián)了大量的字符串。如果使用的是不可變的字符串String,會產(chǎn)生很多可以垃圾回收的對象。這樣既浪費(fèi)時間也浪費(fèi)CPU的運(yùn)算能力,使用可變對象是正確的解決方案(如StringBuilder)。
String result="";
for(String s: arr){
result = result + s;
}
另外一些情況,可變對象剛更加合適可取。例如排序(Collections.sort())。如果Collection是不可變的,排序方法每次將會返回一個新的Collection,這樣會極其浪費(fèi)資源。 可以看看為什么在Java中String被設(shè)計(jì)成不可變?
以上這段代碼出現(xiàn)編譯錯誤,因?yàn)槟J(rèn)的父類構(gòu)造函數(shù)未定義。在Java中,如果一個類沒有定義構(gòu)造函數(shù),編譯器會默認(rèn)插入一個默認(rèn)的無參數(shù)構(gòu)造函數(shù)。如果程序員定義構(gòu)造函數(shù),編譯器將不插入默認(rèn)的無參數(shù)構(gòu)造函數(shù)。上面的代碼由于自定義了有參數(shù)的構(gòu)造函數(shù),編譯器不再插入無參數(shù)的構(gòu)造函數(shù)。子類的構(gòu)造函數(shù),無論是有參數(shù)或無參數(shù),都將調(diào)用父類無參構(gòu)造函數(shù)。當(dāng)子類需要父類的無參數(shù)構(gòu)造函數(shù)的時候,就發(fā)生了錯誤。
解決這個問題,可以1)增加一個父類構(gòu)造函數(shù)
public Super(){
System.out.println("Super");
}
,或2)刪除自定義的父類構(gòu)造函數(shù),或3)添加super(value)到子類構(gòu)造函數(shù)。更多請查看父類和子類的構(gòu)造函數(shù)。
字符串可以通過兩種方式創(chuàng)建:
//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");
這兩者有什么區(qū)別呢? 下面的例子可以提供一個快速的答案:
String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True
關(guān)于它們是如何分配內(nèi)存的更多信息,請查看創(chuàng)建Java字符串使用“”或構(gòu)造函數(shù)?
小結(jié)
以上是我根據(jù)GitHub上的開源項(xiàng)目,Stack Overflow上的問題,和谷歌熱門搜索詞所做的總結(jié)。雖然它們不是準(zhǔn)確的top 10,但很常見的。如果你有不同的觀點(diǎn)或者指出更常見的錯誤,請留言。我也會更新這個列表。非常感謝。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/64162.html
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個錯誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個月,完成了一個相對較大的模塊。由于基礎(chǔ)相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個錯誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個月,完成了一個相對較大的模塊。由于基礎(chǔ)相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個錯誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個月,完成了一個相對較大的模塊。由于基礎(chǔ)相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:下面列舉了我曾經(jīng)犯過的最嚴(yán)重的個相關(guān)的錯誤有些同樣也反映在其他語言數(shù)據(jù)庫的使用上。用服務(wù)器端的驗(yàn)證每個字符串,不要寄希望與。登錄的時候,必須以一個為依據(jù)查找正確的。和是最強(qiáng)有力的競爭者這個兩者都是開源的,而且都沒有被公司收購。 對于大多數(shù)web應(yīng)用來說,數(shù)據(jù)庫都是一個十分基礎(chǔ)性的部分。如果你在使用PHP,那么你很可能也在使用MySQL—LAMP系列中舉足輕重的一份子。對于很多新手們來說...
閱讀 2538·2023-04-26 02:57
閱讀 1420·2023-04-25 21:40
閱讀 2198·2021-11-24 09:39
閱讀 3572·2021-08-30 09:49
閱讀 778·2019-08-30 15:54
閱讀 1181·2019-08-30 15:52
閱讀 2096·2019-08-30 15:44
閱讀 1284·2019-08-28 18:27