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

Java怎樣創(chuàng)建集合才能避免造成內(nèi)存泄漏你了解嗎

 更新時(shí)間:2021年09月29日 08:46:42   作者:Hollis Chuang  
內(nèi)存泄漏是指無用對(duì)象持續(xù)占有內(nèi)存或無用對(duì)象的內(nèi)存得不到及時(shí)釋放,從而造成內(nèi)存空間的浪費(fèi)稱為內(nèi)存泄漏。長生命周期的對(duì)象持有短生命周期對(duì)象的引用就很可能發(fā)生內(nèi)存泄漏,盡管短生命周期對(duì)象已經(jīng)不再需要,但是因?yàn)殚L生命周期持有它的引用而導(dǎo)致不能被回收

由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時(shí)的工作非常繁索。每次建立時(shí)我們都要做:

1、定義一個(gè)空的集合類變量

2、向這個(gè)結(jié)合類中逐一添加元素

3、將集合做為參數(shù)傳遞給方法

例如,要將一個(gè)Set變量傳給一個(gè)方法:

Set users = new HashSet();
users.add("Hollis");
users.add("hollis");
users.add("HollisChuang");
users.add("hollis666");
transferUsers(users);

這樣的寫法稍微有些復(fù)雜,有沒有簡潔的方式呢?

雙括號(hào)語法初始化集合

其實(shí)有一個(gè)比較簡潔的方式,那就是雙括號(hào)語法(double-brace syntax)建立并初始化一個(gè)新的集合:

public class DoubleBraceTest {
    public static void main(String[] args) {
        Set users = new HashSet() {{
            add("Hollis");
            add("hollis");
            add("HollisChuang");
            add("hollis666");
        }};
    }
}

同理,創(chuàng)建并初始化一個(gè)HashMap的語法如下:

Map<String,String> users = new HashMap<>() {{
    put("Hollis","Hollis");
    put("hollis","hollis");
    put("HollisChuang","HollisChuang");
}};

不只是Set、Map,jdk中的集合類都可以用這種方式創(chuàng)建并初始化。

當(dāng)我們使用這種雙括號(hào)語法初始化集合類的時(shí)候,在對(duì)Java文件進(jìn)行編譯時(shí),可以發(fā)現(xiàn)一個(gè)奇怪的現(xiàn)象,使用javac對(duì)DoubleBraceTest進(jìn)行編譯:

javac DoubleBraceTest.java

我們會(huì)發(fā)現(xiàn),得到兩個(gè)class文件:

DoubleBraceTest.class
DoubleBraceTest$1.class

有經(jīng)驗(yàn)的朋友可能一看到這兩個(gè)文件就會(huì)知道,這里面一定用到了匿名內(nèi)部類。

沒錯(cuò),使用這個(gè)雙括號(hào)初始化的效果是創(chuàng)建匿名內(nèi)部類。創(chuàng)建的類有一個(gè)隱式的this指針指向外部類。

不建議使用這種形式

首先,使用這種形式創(chuàng)建并初始化集合會(huì)導(dǎo)致很多內(nèi)部類被創(chuàng)建。因?yàn)槊看问褂秒p大括號(hào)初始化時(shí),都會(huì)生成一個(gè)新類。如這個(gè)例子:

Map hollis = new HashMap(){{
    put("firstName", "Hollis");
    put("lastName", "Chuang");
    put("contacts", new HashMap(){{
        put("0", new HashMap(){{
            put("blogs", "http://www.hollischuang.com");
        }});
        put("1", new HashMap(){{
            put("wechat", "hollischuang");
        }});
    }});
}};

這會(huì)使得很多內(nèi)部類被創(chuàng)建出來:

DoubleBraceTest$1$1$1.class
DoubleBraceTest$1$1$2.class
DoubleBraceTest$1$1.class
DoubleBraceTest$1.class
DoubleBraceTest.class

這些內(nèi)部類被創(chuàng)建出來,是需要被類加載器加載的,這就帶來了一些額外的開銷。

如果您使用上面的代碼在一個(gè)方法中創(chuàng)建并初始化一個(gè)map,并從方法返回該map,那么該方法的調(diào)用者可能會(huì)毫不知情地持有一個(gè)無法進(jìn)行垃圾收集的資源。

public Map getMap() {
    Map hollis = new HashMap(){{
        put("firstName", "Hollis");
        put("lastName", "Chuang");
        put("contacts", new HashMap(){{
            put("0", new HashMap(){{
                put("blogs", "http://www.hollischuang.com");
            }});
            put("1", new HashMap(){{
                put("wechat", "hollischuang");
            }});
        }});
    }};

    return hollis;
}

我們嘗試通過調(diào)用getMap得到這樣一個(gè)通過雙括號(hào)初始化出來的map

public class DoubleBraceTest {
    public static void main(String[] args) {
        DoubleBraceTest doubleBraceTest = new DoubleBraceTest();
        Map map = doubleBraceTest.getMap();
    }
}

返回的Map現(xiàn)在將包含一個(gè)對(duì)DoubleBraceTest的實(shí)例的引用。讀者可以嘗試這通過debug或者以下方式確認(rèn)這一事實(shí)。

Field field = map.getClass().getDeclaredField("this$0");
field.setAccessible(true);
System.out.println(field.get(map).getClass());

替代方案

很多人使用雙括號(hào)初始化集合,主要是因?yàn)樗容^方便,可以在定義集合的同時(shí)對(duì)他進(jìn)行初始化。

但其實(shí),目前已經(jīng)有很多方案可以做這個(gè)事情了,不需要再使用這種存在風(fēng)險(xiǎn)的方案。

使用Arrays工具類

當(dāng)我們想要初始化一個(gè)List的時(shí)候,可以借助Arrays類,Arrays中提供了asList可以把一個(gè)數(shù)組轉(zhuǎn)換成List:

List<String> list2 = Arrays.asList("hollis ", "Hollis", "HollisChuang");

但是需要注意的是,asList 得到的只是一個(gè) Arrays 的內(nèi)部類,是一個(gè)原來數(shù)組的視圖 List,因此如果對(duì)它進(jìn)行增刪操作會(huì)報(bào)錯(cuò)。

使用Stream

Stream是Java中提供的新特性,他可以對(duì)傳入流內(nèi)部的元素進(jìn)行篩選、排序、聚合等中間操作(intermediate operate),最后由最終操作(terminal operation)得到前面處理的結(jié)果。

我們可以借助Stream來初始化集合:

List<String> list1 = Stream.of("hollis", "Hollis", "HollisChuang").collect(Collectors.toList());

使用第三方工具類

很多第三方的集合工具類可以實(shí)現(xiàn)這個(gè)功能,如Guava等:

ImmutableMap.of("k1", "v1", "k2", "v2");
ImmutableList.of("a", "b", "c", "d");

關(guān)于Guava和其中定義的不可變集合,我們?cè)诤竺鏁?huì)詳細(xì)介紹

Java 9內(nèi)置方法

其實(shí)在Java 9 中,在List、Map等集合類中已經(jīng)內(nèi)置了初始化的方法,如List中包含了12個(gè)重載的of方法,就是來做這個(gè)事情的:

/**
 * Returns an unmodifiable list containing zero elements.
 *
 * See <a href="#unmodifiable" rel="external nofollow" >Unmodifiable Lists</a> for details.
 *
 * @param <E> the {@code List}'s element type
 * @return an empty {@code List}
 *
 * @since 9
 */
static <E> List<E> of() {
    return ImmutableCollections.emptyList();
}

static <E> List<E> of(E e1) {
    return new ImmutableCollections.List12<>(e1);
}

static <E> List<E> of(E... elements) {
    switch (elements.length) { // implicit null check of elements
        case 0:
            return ImmutableCollections.emptyList();
        case 1:
            return new ImmutableCollections.List12<>(elements[0]);
        case 2:
            return new ImmutableCollections.List12<>(elements[0], elements[1]);
        default:
            return new ImmutableCollections.ListN<>(elements);
    }
}

到此這篇關(guān)于Java怎樣創(chuàng)建集合才能避免造成內(nèi)存泄漏你了解嗎的文章就介紹到這了,更多相關(guān)Java 集合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)單文件與多文件上傳

    SpringBoot實(shí)現(xiàn)單文件與多文件上傳

    本次例子不基于第三方存儲(chǔ)(如七牛云對(duì)象存儲(chǔ)、阿里云對(duì)象存儲(chǔ)、騰訊云對(duì)象存儲(chǔ)等),僅基于本地存儲(chǔ)。本文主要內(nèi)容如下:公共文件存儲(chǔ)代碼;單文件上傳代碼;多文件上傳代碼
    2021-05-05
  • java使用poi在excel單元格添加超鏈接設(shè)置字體顏色的方法

    java使用poi在excel單元格添加超鏈接設(shè)置字體顏色的方法

    這篇文章主要介紹了java使用poi在excel單元格添加超鏈接,設(shè)置字體顏色,poi功能還是很強(qiáng)大的,基本能想到的功能都能通過poi實(shí)現(xiàn),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 詳解JVM系列之對(duì)象的鎖狀態(tài)和同步

    詳解JVM系列之對(duì)象的鎖狀態(tài)和同步

    鎖和同步是java多線程編程中非常常見的使用場(chǎng)景。為了鎖定多線程共享的對(duì)象,Java需要提供一定的機(jī)制來實(shí)現(xiàn)共享對(duì)象的鎖定。當(dāng)?shù)诙€(gè)線程進(jìn)入同一個(gè)區(qū)域的時(shí)候,必須等待第一個(gè)線程解鎖該對(duì)象。JVM是怎么做到的呢?快來一起看看吧。
    2021-06-06
  • Java Calendar類使用案例詳解

    Java Calendar類使用案例詳解

    這篇文章主要介紹了Java Calendar類使用案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 淺談Java中向上造型向下造型和接口回調(diào)中的問題

    淺談Java中向上造型向下造型和接口回調(diào)中的問題

    這篇文章主要介紹了淺談Java中向上造型向下造型和接口回調(diào)中的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Spring?MVC和springboot靜態(tài)資源處理問題

    Spring?MVC和springboot靜態(tài)資源處理問題

    這篇文章主要介紹了Spring?MVC和springboot靜態(tài)資源處理問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 例題詳解Java?dfs與記憶化搜索和分治遞歸算法的使用

    例題詳解Java?dfs與記憶化搜索和分治遞歸算法的使用

    遞歸指函數(shù)調(diào)用自身。常用的遞歸算法有dfs(深度優(yōu)先搜索)、記憶化搜索和分治,接下來將用幾個(gè)算法題來帶你熟練掌握它
    2022-04-04
  • Java?詳解Collection集合之ArrayList和HashSet

    Java?詳解Collection集合之ArrayList和HashSet

    本章具體介紹了ArrayList和HashSet兩種集合的基本使用方法和區(qū)別,圖解穿插代碼實(shí)現(xiàn)。?JAVA成仙路從基礎(chǔ)開始講,后續(xù)會(huì)講到JAVA高級(jí),中間會(huì)穿插面試題和項(xiàng)目實(shí)戰(zhàn),希望能給大家?guī)韼椭?/div> 2022-03-03
  • Java實(shí)現(xiàn)走迷宮回溯算法

    Java實(shí)現(xiàn)走迷宮回溯算法

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)走迷宮回溯算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • JAVA實(shí)現(xiàn) SpringMVC方式的微信接入、實(shí)現(xiàn)簡單的自動(dòng)回復(fù)功能

    JAVA實(shí)現(xiàn) SpringMVC方式的微信接入、實(shí)現(xiàn)簡單的自動(dòng)回復(fù)功能

    這篇文章主要介紹了JAVA實(shí)現(xiàn) SpringMVC方式的微信接入、實(shí)現(xiàn)簡單的自動(dòng)回復(fù)功能的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11

最新評(píng)論

建始县| 开原市| 金昌市| 长顺县| 常德市| 枣阳市| 黄陵县| 公主岭市| 内黄县| 抚松县| 临湘市| 定边县| 沽源县| 宁强县| 湖口县| 黎平县| 阿尔山市| 海盐县| 义乌市| 泸定县| 兴安县| 柘城县| 五莲县| 北安市| 鞍山市| 鄂伦春自治旗| 建瓯市| 修武县| 靖江市| 开封市| 松潘县| 长寿区| 来安县| 曲沃县| 高阳县| 岱山县| 湖南省| 寿光市| 平阳县| 宁明县| 梓潼县|