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

Java接口中盡量避免使用數(shù)組

 更新時(shí)間:2015年07月10日 10:58:35   投稿:goldensun  
這篇文章主要介紹了Java接口中盡量避免使用數(shù)組的建議,根據(jù)實(shí)際示例展示了接口中使用數(shù)組而造成的影響程序速度的現(xiàn)象,需要的朋友可以參考下

 如果你發(fā)現(xiàn)在一個(gè)接口使用有如下定義方法:
 

public String[] getParameters();

那么你應(yīng)該認(rèn)真反思。數(shù)組不僅僅老式,而且我們有合理的理由避免暴露它們。在這篇文章中,我將試圖總結(jié)在Java API中使用數(shù)組的缺陷。首先從最出人意料的一個(gè)例子開(kāi)始。
數(shù)組導(dǎo)致性能不佳

你可能認(rèn)為使用數(shù)組是最快速的,因?yàn)閿?shù)組是大多數(shù)collection實(shí)現(xiàn)的底層數(shù)據(jù)結(jié)構(gòu)。使用一個(gè)純數(shù)組怎么會(huì)比使用一個(gè)包含數(shù)組的對(duì)象性能更低?


讓我們先從這個(gè)看起來(lái)很熟悉的普遍的習(xí)慣用法開(kāi)始:
 

public String[] getNames() {
 return namesList.toArray( new String[ namesList.size() ] );
}

這個(gè)方法從一個(gè)用來(lái)在其內(nèi)部保存數(shù)據(jù)的可變集合處創(chuàng)建了一個(gè)數(shù)據(jù). 它通過(guò)提供一個(gè)確切大小的數(shù)組來(lái)嘗試優(yōu)化數(shù)組的創(chuàng)建. 有趣的是,這一“優(yōu)化”使得其比下面的更簡(jiǎn)單的版本速度還要慢(請(qǐng)看圖表中綠色VS橘色條):
 

public String[] getNames() {
 return namesList.toArray( new String[ 0 ] );
}

不過(guò),如果方法返回的是一個(gè)List, 創(chuàng)建防御式的副本又更加的快了 (紅條):
 

public List<String> getNames() {
 return new ArrayList( namesList );
}

不同之處在于一個(gè)ArrayList將它的數(shù)據(jù)項(xiàng)放在一個(gè)Object[]數(shù)組中,并且使用的是無(wú)類(lèi)型的toArray方法,其比有類(lèi)型的方法要快很多(藍(lán)條). 這是類(lèi)型安全的,因?yàn)闊o(wú)類(lèi)型的數(shù)組時(shí)封裝在由編譯器檢查的泛型類(lèi)型ArrayList<T>中的.

2015710105938872.png (664×146)

這個(gè)圖標(biāo)展示了一個(gè)在Java 7上n=5的參考標(biāo)準(zhǔn). 不過(guò),更多的數(shù)據(jù)項(xiàng)或者是另外一個(gè)VM情況系啊,這幅圖片并不會(huì)改變太多. CPU的開(kāi)銷(xiāo)可能并不會(huì)太劇烈,但是會(huì)有增長(zhǎng). 機(jī)會(huì)有一個(gè)數(shù)組的使用者應(yīng)該將其轉(zhuǎn)換到一個(gè)集合中去,以便利用它做任何事情, 然后將結(jié)果轉(zhuǎn)換回一個(gè)數(shù)組,來(lái)送進(jìn)另外一個(gè)接口的方法中,諸如此類(lèi)做法.

是用一個(gè)簡(jiǎn)單的ArrayList,而不是一個(gè)數(shù)組來(lái)提升性能,無(wú)需再動(dòng)太多的手腳. ArrayList 為封裝的數(shù)組增加了32字節(jié)的恒定開(kāi)銷(xiāo). 例如,一個(gè)有十個(gè)對(duì)象的數(shù)組需要104字節(jié),一個(gè)ArrayList 136字節(jié).

使用 集合,你甚至可能決定返回內(nèi)部列表的一個(gè)不可修改的版本:
 

public List<String> getNames() {
 return Collections.unmodifiableList( namesList );
}

此操作會(huì)在固定的市價(jià)運(yùn)行,因此他比任何上述其它的方法都要快很多(黃條). 其同一個(gè)防御式的拷貝不同。一個(gè)不可修改的集合將會(huì)在你的內(nèi)部數(shù)據(jù)變化時(shí)跟著變化。如果變化發(fā)生了,客戶(hù)端會(huì)在迭代數(shù)據(jù)項(xiàng)時(shí)運(yùn)行到一個(gè)ConcurrentModificationException中. 可以認(rèn)為它是一個(gè)糟糕的設(shè)計(jì),接口提供了一個(gè)在運(yùn)行時(shí)拋出一個(gè)UnsupportedOperationException. 不過(guò),至少對(duì)于內(nèi)部的使用,這個(gè)方法對(duì)于一個(gè)防御式的拷貝而言,會(huì)是一個(gè)高性能的選擇 - 一些不可能使用數(shù)組實(shí)現(xiàn)的東西.

數(shù)組定義一個(gè)結(jié)構(gòu),而不是一個(gè)接口

Java 是一門(mén)面向?qū)ο蟮恼Z(yǔ)言。面向?qū)ο蟮暮诵母拍罹褪翘峁┮恍┓椒▉?lái)訪問(wèn)和操作它們的數(shù)據(jù),而不是直接對(duì)數(shù)據(jù)域進(jìn)行操作. 這些方法創(chuàng)建一個(gè)接口來(lái)描述你可以在對(duì)象上面做的事情.

由于java已經(jīng)對(duì)性能做了設(shè)計(jì),原生類(lèi)型和數(shù)組已經(jīng)被融合進(jìn)了類(lèi)型系統(tǒng)之中. 對(duì)象可以使用數(shù)組來(lái)在內(nèi)容高效地存儲(chǔ)數(shù)據(jù). 然而,即使通過(guò)數(shù)組來(lái)呈現(xiàn)一個(gè)可變集合的元素,它們也不會(huì)提供任何方法來(lái)訪問(wèn)和操作這些元素. 事實(shí)上,除了直接訪問(wèn)的替換元素之外,在數(shù)組上你沒(méi)有多少其它事情可以做. 數(shù)組甚至連toString 和 equals 都沒(méi)有一個(gè)有意義的實(shí)現(xiàn), 而集合卻有:
 

String[] array = { "foo", "bar" };
List<String> list = Arrays.asList( array );
 
System.out.println( list );
// -> [foo, bar]
System.out.println( array );
// -> [Ljava.lang.String;@6f548414
 
list.equals( Arrays.asList( "foo", "bar" ) )
// -> true
array.equals( new String[] { "foo", "bar" } )
// -> false

不同于數(shù)組,集合的 API 提供了許多有用的方法來(lái)訪問(wèn)元素. 用戶(hù)可以檢查包含的元素,提取子列表或者計(jì)算交集. 集合可以向數(shù)據(jù)層添加特定的特性, 諸如線程安全,同時(shí)將實(shí)現(xiàn)原理保持在內(nèi)部可見(jiàn).

通過(guò)使用一個(gè)數(shù)據(jù),你定義了數(shù)據(jù)被保存在內(nèi)存中的哪個(gè)地方. 通過(guò)使用一個(gè)集合,你定義了用戶(hù)可以在數(shù)據(jù)上做的操作.

數(shù)組不是類(lèi)型安全的

如果你依賴(lài)于編譯器檢查的類(lèi)型安全,小心對(duì)象數(shù)組. 下面的代碼會(huì)在運(yùn)行時(shí)奔潰,但是編譯器找不出問(wèn)題所在:

Number[] numbers = new Integer[10];
numbers[0] = Long.valueOf( 0 ); // throws ArrayStoreException

原因是數(shù)組是“協(xié)變式”的, 比如,如果 T 是S 的一個(gè)子類(lèi)型, 那么 T[] 就會(huì)是 S[] 的一個(gè)子類(lèi)型. Joshua Bloch 在其著作 Effective Java 涵蓋了所有的理論, 每一個(gè)Java開(kāi)發(fā)者必讀.

歸因于這個(gè)行為,暴露數(shù)組類(lèi)型的接口允許返回聲明數(shù)組類(lèi)型的一個(gè)子類(lèi)型, 導(dǎo)致了一個(gè)怪異的運(yùn)行時(shí)異常.


Bloch 同時(shí)也解釋說(shuō),數(shù)組與泛型類(lèi)型不兼容. 因?yàn)閿?shù)組會(huì)在運(yùn)行時(shí)強(qiáng)制要求有類(lèi)型信息,而泛型則會(huì)在編譯時(shí)被檢查,泛型類(lèi)型不能被放到數(shù)組中.

  •     一般而言,數(shù)組和泛型不能很好的融合。如果你發(fā)現(xiàn)自己在融合它們而得到了一個(gè)編譯時(shí)錯(cuò)誤或者警告,那你的第一反應(yīng)應(yīng)該是用list去替換數(shù)組.

- Joshua Bloch, Effective Java (第二版), 第29條
總結(jié)

數(shù)組底層的語(yǔ)言構(gòu)造、它們會(huì)被用在實(shí)現(xiàn)中,但是它們不應(yīng)該想其它的類(lèi)暴露. 在一個(gè)接口方法中使用數(shù)組違背了面向?qū)ο蟮脑瓌t,它會(huì)導(dǎo)致違和的API,并且它也可能給類(lèi)型安全和性能造成短板.

相關(guān)文章

  • 使用Lombok的@Builder注解帶來(lái)的兩大坑

    使用Lombok的@Builder注解帶來(lái)的兩大坑

    這篇文章主要介紹了使用Lombok的@Builder注解帶來(lái)的兩大坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Spring?boot整合ELK詳細(xì)過(guò)程

    Spring?boot整合ELK詳細(xì)過(guò)程

    ELK是由Elasticsearch、Logstash和Kibana三個(gè)開(kāi)源軟件組成的技術(shù)堆棧,主要用于數(shù)據(jù)的存儲(chǔ)、處理和可視化,本文給大家介紹Spring?boot整合ELK詳細(xì)過(guò)程,感興趣的朋友一起看看吧
    2024-01-01
  • 由淺到深帶你詳談Java實(shí)現(xiàn)數(shù)組擴(kuò)容的三種方式

    由淺到深帶你詳談Java實(shí)現(xiàn)數(shù)組擴(kuò)容的三種方式

    這篇文章主要詳細(xì)介紹了Java實(shí)現(xiàn)數(shù)組擴(kuò)容的三種方式,新建一個(gè)數(shù)組,把原來(lái)數(shù)組的內(nèi)容搬到新數(shù)組中,使用system.arraycopy(),使用java.util.Arrays.copyOf()這三種方式,具有一定的參考價(jià)值,需要的朋友可以借鑒一下
    2023-06-06
  • Spring中@RequestMapping、@RestController和Postman

    Spring中@RequestMapping、@RestController和Postman

    本文介紹了Spring框架中常用的@RequestMapping和@RestController注解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • Java面試必問(wèn)之ThreadLocal終極篇分享

    Java面試必問(wèn)之ThreadLocal終極篇分享

    ThreadLocal是什么呢?其實(shí)ThreadLocal并非是一個(gè)線程的本地實(shí)現(xiàn)版本,它并不是一個(gè)Thread,而是thread local variable(線程局部變量),這篇文章主要給大家介紹了關(guān)于Java面試必問(wèn)之ThreadLocal終極篇的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • Spring?boot框架JWT實(shí)現(xiàn)用戶(hù)賬戶(hù)密碼登錄驗(yàn)證流程

    Spring?boot框架JWT實(shí)現(xiàn)用戶(hù)賬戶(hù)密碼登錄驗(yàn)證流程

    這篇文章主要介紹了Springboot框架JWT實(shí)現(xiàn)用戶(hù)賬戶(hù)密碼登錄驗(yàn)證,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • 如何解決Maven無(wú)法拉取SNAPSHOT依賴(lài)問(wèn)題

    如何解決Maven無(wú)法拉取SNAPSHOT依賴(lài)問(wèn)題

    在使用Maven管理項(xiàng)目時(shí),可能會(huì)遇到無(wú)法拉取SNAPSHOT版本依賴(lài)的問(wèn)題,這通常是因?yàn)镸aven默認(rèn)不支持直接拉取SNAPSHOT版本,遇到這樣的問(wèn)題,可以通過(guò)在項(xiàng)目的pom.xml文件中添加<repositories>標(biāo)簽,并配置啟用SNAPSHOT的倉(cāng)庫(kù)地址來(lái)解決
    2024-10-10
  • Java中的Collections類(lèi)的使用示例詳解

    Java中的Collections類(lèi)的使用示例詳解

    Collections類(lèi)提供了一些靜態(tài)方法,這些方法能夠?qū)ist集合實(shí)現(xiàn)常用的算法操作,這些算法是排序,填充,移位和查找等。本文將通過(guò)示例為大家詳細(xì)講講Collections類(lèi)的使用,需要的可以參考一下
    2022-12-12
  • idea中的jvm調(diào)優(yōu)方式

    idea中的jvm調(diào)優(yōu)方式

    這篇文章主要介紹了idea中的jvm調(diào)優(yōu)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 簡(jiǎn)單了解java自定義和自然排序

    簡(jiǎn)單了解java自定義和自然排序

    這篇文章主要介紹了簡(jiǎn)單了解java自定義和自然排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07

最新評(píng)論

阜新| 阿克| 白山市| 珲春市| 霍州市| 环江| 松潘县| 上蔡县| 乌拉特中旗| 通榆县| 永昌县| 香港| 白玉县| 新龙县| 贺州市| 伊通| 唐山市| 哈尔滨市| 进贤县| 苏州市| 榆社县| 文水县| 正宁县| 昌乐县| 武安市| 金阳县| 孙吴县| 霍城县| 开远市| 周宁县| 陇西县| 望奎县| 来宾市| 通化县| 富民县| 吴旗县| 金湖县| 昭通市| 宿松县| 万源市| 盐山县|