<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    paulwong

    Java程序員們最常犯的10個錯誤

    1.將數組轉化為列表

    將數組轉化為一個列表時,程序員們經常這樣做:

    List<String> list = Arrays.asList(arr);

    Arrays.asList()會返回一個ArrayList對象,ArrayList類是Arrays的一個私有靜態類,而不是java.util.ArrayList類,java.util.Arrays.ArrayList類有set()、get()、contains()方法,但是沒有增加元素的方法,所以它的大小是固定的,想要創建一個真正的ArrayList類,你應該這樣做:

    ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

    ArrayList的構造方法可以接受一個集合類型,剛好它也是java.util.Arrays.ArrayList的超類。

    2.判斷一個數組是否包含一個值

    程序員們經常這樣做:

    Set<String> set = new HashSet<String>(Arrays.asList(arr)); 
    return set.contains(targetValue);

    這段代碼起作用,但是沒有必要把一個數組轉化成列表,轉化為列表需要額外的時間。它可以像下面那樣簡單:

    Arrays.asList(arr).contains(targetValue);

    或者是:

    for(String s:arr){
    if(s.equals(targetValue)){
    return true;
    }
    }
    return false;

    第一種方法比第二種更容易讀

    3.在一個循環中刪除一個列表中的元素

    思考下面這一段在循環中刪除多個元素的的代碼

    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);

    輸出結果是:

    [b,d]

    在這個方法中有一個嚴重的錯誤。當一個元素被刪除時,列表的大小縮小并且下標變化,所以當你想要在一個循環中用下標刪除多個元素的時候,它并不會正常的生效。

    你也許知道在循環中正確的刪除多個元素的方法是使用迭代,并且你知道java中的foreach循環看起來像一個迭代器,但實際上并不是。考慮一下下面的代碼:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));

    for(String s:list){
        if(s.equals("a")){
          list.remove(s);
        }
    }

    它會拋出一個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()之前調用。在一個foreach循環中,編譯器會使.next()在刪除元素之后被調用,因此就會拋出ConcurrentModificationException異常,你也許希望看一下ArrayList.iterator()的源代碼。

    4.Hashtable與HashMap的對比

    就算法而言,哈希表是數據結構的一個名字。但是在java中,這個數據結構的名字是HashMap。Hashtable與HashMap的一個重要不同點是Hashtable是同步的。所以你經常不需要Hashtable,相反HashMap經常會用到。

    具體請看:

    HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
    Top 10 questions about Map

    5.在集合中使用原始類型

    在Java中原始類型與無界通配符類型很容易混合在一起,拿Set來說,Set是一個原始類型,而Set<?>是無界的通配符類型。
    考慮下面使用原始類型List作為參數的代碼:

    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);

    這段代碼會拋出一個異常:

    Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

    at ...

    使用原生類型集合是危險的,這是因為原生類型集合跳過了泛型類型檢查,并且不是安全的,在Set、Set<?>和Set<Object>中有很大的不同,具體請看Raw type vs. Unbounded wildcard和Type Erasure。

    6.訪問級別

    程序員們經常使用public作為類字段的修飾符,可以很簡單的通過引用得到值,但這是一個壞的設計,按照經驗,分配給成員變量的訪問級別應該盡可能的低。

    具體請看:public, default, protected, and private

    7.ArrayList與LinkedList的對比

    當程序員們不知道ArrayList與LinkedList的區別時,他們經常使用ArrayList,因為它看起來比較熟悉。
    然而,它們之前有巨大的性能差別。簡而言之,如果有大量的增加刪除操作并且沒有很多的隨機訪問元素的操作,應該首先LinkedList。
    如果你剛接觸它們,請查看ArrayList vs. LinkedList來獲得更多關于它們性能的信息。

    8.可變與不可變

    不可變對象有許多的優點,比如簡單,安全等等。但是對于每一個不同的值都需要一個獨立的對象,太多的對象可能會造成大量的垃圾回收。
    當選擇可變與不可變時應該有一個平衡。
    一般的,可變對象用來避免產生大量的中間對象。一個典型的例子是連接大量的字符串。
    如果你用一個不可變的字符串,你會產生很多需要進行垃圾回收的對象。這很浪費CPU的時間,使用可變對象是正確的解決方案(比如StringBuilder)。

    String result="";
    for(String s: arr){
      result = result + s;
    }

    有時在某些情況下也是需要可變對象的,比如將可變對象作為參數傳入方法,你不用使用很多語句便可以得到多個結果。
    另外一個例子是排序和過濾:當然,你可以寫一個方法來接收原始的集合,并且返回一個排好序的集合,但是那樣對于大的集合就太浪費了。(來自StackOverFlow的dasblinkenlight’s的答案)

    具體請看:Why String is Immutable?

    9.父類與子類的構造函數




    這個編譯期錯誤的出現是父類默認的構造方法未定義,在java中,如果一個類沒有定義構造方法,編譯器會默認的為這個類添加一個無參的構造方法。如果在父類中定義了構造方法,在這個例子中是Super(String s),編譯器就不會添加默認的無參構造方法,這就是上面這個父類的情形。

    子類的構造器,不管是無參還有有參,都會調用父類的無參構造器。因為編譯器試圖在子類的兩個構造方法中添加super()方法。但是父類默認的構造方法未定義,編譯器就會報出這個錯誤信息。

    想要修復這個問題,可以簡單的通過1)在父類中添加一個Super()構造方法,像下面這樣:

    public Super(){
      System.out.println("Super");
    }

    或者2)移除父類自定義的構造方法,或者3)在子類的構造方法中調用父類的super(value)方法。

    具體請看:Constructor of Super and Stub

    10.使用" "還是構造器

    有兩種方式可以創建字符串:

    //1.使用字符串
    String x = "abc";
    //2.使用構造器
    String y = new String("abc");

    有什么區別?

    下面的例子會給出一個快速的答案:

    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

    關于它們內存分配的更多信息,請參考Create Java String Using ” ” or Constructor?.

    將來的工作

    這個列表是我基于大量的github上的開源項目,Stack overflow上的問題,還有一些流行的google搜索的分析。沒有明顯示的評估證明它們是前10,但它們絕對是很常見的。如果您不同意任一部分,請留下您的評論。如果您能提出其它一些常見的錯誤,我將會非常感激。

    原文鏈接: programcreek 翻譯: ImportNew.com - 林林
    譯文鏈接: http://www.importnew.com/12074.html 

    posted on 2014-07-04 10:44 paulwong 閱讀(300) 評論(0)  編輯  收藏 所屬分類: J2SE

    主站蜘蛛池模板: 永久在线毛片免费观看| 性色av极品无码专区亚洲| 亚洲精品黄色视频在线观看免费资源| 99热在线免费观看| 一级毛片免费在线| 亚洲爆乳成av人在线视菜奈实| 亚洲精品国产手机| 久久亚洲国产精品| 久久久久亚洲爆乳少妇无| 国产jizzjizz视频全部免费| 成人免费一区二区无码视频| 亚洲视频在线免费播放| 久久九九AV免费精品| 国产成年无码久久久免费| 一级女性全黄久久生活片免费 | 久久aⅴ免费观看| av午夜福利一片免费看久久| 国产精品亚洲一区二区三区| 亚洲无码一区二区三区| 国产日本亚洲一区二区三区| 67pao强力打造67194在线午夜亚洲| 亚洲无av在线中文字幕| 国产精品亚洲二区在线观看| 免费大黄网站在线观| 免费h成人黄漫画嘿咻破解版| 免费精品一区二区三区在线观看| 最近最新的免费中文字幕| 韩国免费一级成人毛片| 69堂人成无码免费视频果冻传媒| 777爽死你无码免费看一二区| 人妻无码久久一区二区三区免费| a级毛片在线免费观看| 野花香高清视频在线观看免费 | 亚洲精品无码国产| 国产日韩亚洲大尺度高清| 亚洲精品乱码久久久久久按摩| 亚洲中文字幕在线观看| 亚洲大成色www永久网站| 亚洲精品免费在线观看| 亚洲高清日韩精品第一区| 亚洲人成在线免费观看|