最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java項(xiàng)目開發(fā)中最容易犯的10個錯誤與解決

 更新時(shí)間:2026年03月16日 08:19:23   作者:越重天  
作為 Java 開發(fā),我們在寫代碼的過程中難免會產(chǎn)生各種奇思妙想的 bug ,有些 bug 就挺讓人無奈的,下面小編就和大家詳細(xì)介紹一下如何避免吧

作為 Java 開發(fā),我們在寫代碼的過程中難免會產(chǎn)生各種奇思妙想的 bug ,有些 bug 就挺讓人無奈的,比如說各種空指針異常,在 ArrayList 的迭代中進(jìn)行刪除操作引發(fā)異常,數(shù)組下標(biāo)越界異常等。

錯誤一:Array 轉(zhuǎn)換成 ArrayList

Array 轉(zhuǎn)換成 ArrayList 還能出錯?這是哪個笨。。。。。。

等等,你先別著急說,先來看看是怎么回事。

如果要將數(shù)組轉(zhuǎn)換為 ArrayList,我們一般的做法會是這樣

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

Arrays.asList() 將返回一個 ArrayList,它是 Arrays 中的私有靜態(tài)類,它不是 java.util.ArrayList 類。如下圖所示

Arrays 內(nèi)部的 ArrayList 只有 set、get、contains 等方法,但是沒有能夠像是 add 這種能夠使其內(nèi)部結(jié)構(gòu)進(jìn)行改變的方法,所以 Arrays 內(nèi)部的 ArrayList 的大小是固定的。

如果要創(chuàng)建一個能夠添加元素的 ArrayList ,你可以使用下面這種創(chuàng)建方式:

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

因?yàn)?ArrayList 的構(gòu)造方法是可以接收一個 Collection 集合的,所以這種創(chuàng)建方式是可行的。

錯誤二:檢查數(shù)組是否包含某個值

檢查數(shù)組中是否包含某個值,部分程序員經(jīng)常會這么做:

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

這段代碼雖然沒錯,但是有額外的性能損耗,正常情況下,不用將其再轉(zhuǎn)換為 set,直接這么做就好了:

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

或者使用下面這種方式(窮舉法,循環(huán)判斷)

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

上面第一段代碼比第二段更具有可讀性。

錯誤三:在 List 中循環(huán)刪除元素

這個錯誤我相信很多小伙伴都知道了,在循環(huán)中刪除元素是個禁忌,有段時(shí)間內(nèi)我在審查代碼的時(shí)候就喜歡看團(tuán)隊(duì)的其他小伙伴有沒有犯這個錯誤。

說到底,為什么不能這么做(集合內(nèi)刪除元素)呢?且看下面代碼

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é)果你能想到么?是不是蠢蠢欲動想試一波了?

答案其實(shí)是 [b,d]

為什么只有兩個值?我這不是循環(huán)輸出的么?

其實(shí),在列表內(nèi)部,當(dāng)你使用外部 remove 的時(shí)候,一旦 remove 一個元素后,其列表的內(nèi)部結(jié)構(gòu)會發(fā)生改變,一開始集合總?cè)萘渴?4,remove 一個元素之后就會變?yōu)?3,然后再和 i 進(jìn)行比較判斷。。。。。。所以只能輸出兩個元素。

你可能知道使用迭代器是正確的 remove 元素的方式,你還可能知道 for-each 和 iterator 這種工作方式類似,所以你寫下了如下代碼

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
	if (s.equals("a"))
		list.remove(s);
}

然后你充滿自信的 run xxx.main() 方法,結(jié)果。。。。。。ConcurrentModificationException

為啥呢?

那是因?yàn)槭褂?ArrayList 中外部 remove 元素,會造成其內(nèi)部結(jié)構(gòu)和游標(biāo)的改變。

在阿里開發(fā)規(guī)范上,也有不要在 for-each 循環(huán)內(nèi)對元素進(jìn)行 remove/add 操作的說明。

所以大家要使用 List 進(jìn)行元素的添加或者刪除操作,一定要使用迭代器進(jìn)行刪除。也就是

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)用。 在 foreach 循環(huán)中,編譯器會在刪除元素的操作后調(diào)用 .next(),導(dǎo)致ConcurrentModificationException。

錯誤四:Hashtable 和 HashMap

這是一條算法方面的規(guī)約:按照算法的約定,Hashtable 是數(shù)據(jù)結(jié)構(gòu)的名稱,但是在 Java 中,數(shù)據(jù)結(jié)構(gòu)的名稱是 HashMap,Hashtable 和 HashMap 的主要區(qū)別之一就是 Hashtable 是同步的,所以很多時(shí)候你不需要 Hashtable ,而是使用 HashMap。

錯誤五:使用原始類型的集合

這是一條泛型方面的約束:

在 Java 中,原始類型和無界通配符類型很容易混合在一起。以 Set 為例,Set 是原始類型,而 Set<?> 是無界通配符類型。

比如下面使用原始類型 List 作為參數(shù)的代碼:

public static void add(List list, Object o){
	list.add(o);
}
public static void main(String[] args){
	List<String> list = new ArrayList<String>();
	add(list, 10);
	String s = list.get(0);
}

這段代碼會拋出 java.lang.ClassCastException 異常,為啥呢?

使用原始類型集合是比較危險(xiǎn)的,因?yàn)樵碱愋蜁^泛型檢查而且不安全,Set、Set<?> 和 Set<Object> 存在巨大的差異,而且泛型在使用中很容易造成類型擦除。

大家都知道,Java 的泛型是偽泛型,這是因?yàn)?Java 在編譯期間,所有的泛型信息都會被擦掉,正確理解泛型概念的首要前提是理解類型擦除。Java 的泛型基本上都是在編譯器這個層次上實(shí)現(xiàn)的,在生成的字節(jié)碼中是不包含泛型中的類型信息的,使用泛型的時(shí)候加上類型參數(shù),在編譯器編譯的時(shí)候會去掉,這個過程成為類型擦除。

如在代碼中定義List<Object>List<String>等類型,在編譯后都會變成List,JVM 看到的只是List,而由泛型附加的類型信息對 JVM 是看不到的。Java 編譯器會在編譯時(shí)盡可能的發(fā)現(xiàn)可能出錯的地方,但是仍然無法在運(yùn)行時(shí)刻出現(xiàn)的類型轉(zhuǎn)換異常的情況,類型擦除也是 Java 的泛型與 C++ 模板機(jī)制實(shí)現(xiàn)方式之間的重要區(qū)別。

比如下面這段示例

public class Test {

    public static void main(String[] args) {

        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("abc");

        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(123);

        System.out.println(list1.getClass() == list2.getClass());
    }

}

在這個例子中,我們定義了兩個ArrayList數(shù)組,不過一個是ArrayList<String>泛型類型的,只能存儲字符串;一個是ArrayList<Integer>泛型類型的,只能存儲整數(shù),最后,我們通過list1對象和list2對象的getClass()方法獲取他們的類的信息,最后發(fā)現(xiàn)結(jié)果為true。說明泛型類型StringInteger都被擦除掉了,只剩下原始類型。

所以,最上面那段代碼,把 10 添加到 Object 類型中是完全可以的,然而將 Object 類型的 “10” 轉(zhuǎn)換為 String 類型就會拋出類型轉(zhuǎn)換異常。

錯誤六:訪問級別問題

我相信大部分開發(fā)在設(shè)計(jì) class 或者成員變量的時(shí)候,都會簡單粗暴的直接聲明 public xxx,這是一種糟糕的設(shè)計(jì),這樣對于類或者成員變量來說,都存在一定危險(xiǎn)性。

錯誤七:ArrayList 和 LinkedList

哈哈哈,ArrayList 是我見過程序員使用頻次最高的工具類,沒有之一。

當(dāng)開發(fā)人員不知道 ArrayList 和 LinkedList 的區(qū)別時(shí),他們經(jīng)常使用 ArrayList(其實(shí)實(shí)際上,就算知道他們的區(qū)別,他們也不用 LinkedList,因?yàn)檫@點(diǎn)性能不值一提),因?yàn)榭雌饋?ArrayList 更熟悉。。。。。。

但是實(shí)際上,ArrayList 和 LinkedList 存在巨大的性能差異,簡而言之,如果添加/刪除操作大量且隨機(jī)訪問操作不是很多,則應(yīng)首選 LinkedList。如果存在大量的訪問操作,那么首選 ArrayList,但是 ArrayList 不適合進(jìn)行大量的添加/刪除操作。

錯誤八:可變和不可變

不可變對象有很多優(yōu)點(diǎn),比如簡單、安全等。但是不可變對象需要為每個不同的值分配一個單獨(dú)的對象,對象不具備復(fù)用性,如果這類對象過多可能會導(dǎo)致垃圾回收的成本很高。在可變和不可變之間進(jìn)行選擇時(shí)需要有一個平衡。

一般來說,可變對象用于避免產(chǎn)生過多的中間對象。 比如你要連接大量字符串。 如果你使用一個不可變的字符串,你會產(chǎn)生很多可以立即進(jìn)行垃圾回收的對象。 這會浪費(fèi) CPU 的時(shí)間和精力,使用可變對象是正確的解決方案(例如 StringBuilder)。如下代碼所示:

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

所以,正確選擇可變對象還是不可變對象需要慎重抉擇。

錯誤九:構(gòu)造函數(shù)

首先看一段代碼,分析為什么會編譯不通過?

發(fā)生此編譯錯誤是因?yàn)槲炊x默認(rèn) Super 的構(gòu)造函數(shù)。 在 Java 中,如果一個類沒有定義構(gòu)造函數(shù),編譯器會默認(rèn)為該類插入一個默認(rèn)的無參數(shù)構(gòu)造函數(shù)。 如果在 Super 類中定義了構(gòu)造函數(shù),在這種情況下 Super(String s),編譯器將不會插入默認(rèn)的無參數(shù)構(gòu)造函數(shù)。 這就是上面 Super 類的情況。

要想解決這個問題,只需要在 Super 中添加一個無參數(shù)的構(gòu)造函數(shù)即可。

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

錯誤十:到底是使用 “” 還是構(gòu)造函數(shù)

考慮下面代碼:

String x = "abc";
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

這就是一個典型的內(nèi)存分配問題。

以上就是Java項(xiàng)目開發(fā)中最容易犯的10個錯誤與解決的詳細(xì)內(nèi)容,更多關(guān)于Java開發(fā)易犯錯誤的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java synchronized關(guān)鍵字從入門到原理解析

    Java synchronized關(guān)鍵字從入門到原理解析

    這篇文章介紹Java synchronized關(guān)鍵字從入門到原理,本課程適合具備Java基礎(chǔ)語法知識,初步了解多線程概念但尚未系統(tǒng)學(xué)習(xí)并發(fā)編程的開發(fā)者,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2026-02-02
  • 詳解Java中的封裝、繼承、多態(tài)

    詳解Java中的封裝、繼承、多態(tài)

    本文主要介紹了Java中的封裝、繼承、多態(tài)的相關(guān)知識,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • SpringBoot2.x過后static下的靜態(tài)資源無法訪問的問題

    SpringBoot2.x過后static下的靜態(tài)資源無法訪問的問題

    這篇文章主要介紹了SpringBoot2.x過后static下的靜態(tài)資源無法訪問的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Java中Object.equals和String.equals的區(qū)別詳解

    Java中Object.equals和String.equals的區(qū)別詳解

    這篇文章主要給大家介紹了Java中Object.equals和String.equals的區(qū)別,文中通過一個小示例讓大家輕松的明白這兩者的區(qū)別,對大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-04-04
  • Spring Cloud Gateway入門解讀

    Spring Cloud Gateway入門解讀

    本篇文章主要介紹了Spring Cloud Gateway入門解讀,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 使用CI/CD工具Github Action發(fā)布jar到Maven中央倉庫的詳細(xì)介紹

    使用CI/CD工具Github Action發(fā)布jar到Maven中央倉庫的詳細(xì)介紹

    今天通過對Github Action的簡單使用來介紹了CI/CD的作用,這個技術(shù)體系是項(xiàng)目集成交付的趨勢,也是面試中的一個亮點(diǎn)技能。 而且這種方式可以實(shí)現(xiàn)“一次配置,隨時(shí)隨地集成部署”,感興趣的朋友一起看看吧
    2021-07-07
  • Java中Velocity快速對變量中的引號特殊字符進(jìn)行轉(zhuǎn)義

    Java中Velocity快速對變量中的引號特殊字符進(jìn)行轉(zhuǎn)義

    Velocity是一個基于Java的模板引擎,與Freemarker類似,這篇文章主要介紹了Java中Velocity如何對變量中的引號特殊字符進(jìn)行轉(zhuǎn)義,主要記錄一下在使用中碰到的要對引號特殊字符進(jìn)行轉(zhuǎn)義的問題,需要的朋友可以參考下
    2023-07-07
  • Java png圖片修改像素rgba值的操作

    Java png圖片修改像素rgba值的操作

    這篇文章主要介紹了Java png圖片修改像素rgba值的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • struts2實(shí)現(xiàn)簡單文件下載功能

    struts2實(shí)現(xiàn)簡單文件下載功能

    這篇文章主要為大家詳細(xì)介紹了struts2實(shí)現(xiàn)簡單文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java編程 中流對象選取規(guī)律詳解

    java編程 中流對象選取規(guī)律詳解

    下面小編就為大家?guī)硪黄猨ava編程 中流對象選取規(guī)律詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01

最新評論

西安市| 凤山县| 新余市| 海晏县| 江油市| 龙里县| 潍坊市| 台湾省| 东乡族自治县| 兰溪市| 东乡| 西峡县| 阳山县| 巴南区| 利川市| 新兴县| 长汀县| 左云县| 溆浦县| 达日县| 海南省| 巴里| 栖霞市| 凤冈县| 仪陇县| 晋中市| 乌鲁木齐县| 庆云县| 东光县| 呼伦贝尔市| 丹棱县| 府谷县| 宁城县| 阿鲁科尔沁旗| 陆川县| 万山特区| 策勒县| 濮阳县| 吉水县| 会同县| 临武县|