程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java接口中盡可能防止應用數組

Java接口中盡可能防止應用數組

編輯:關於JAVA

Java接口中盡可能防止應用數組。本站提示廣大學習愛好者:(Java接口中盡可能防止應用數組)文章只能為提供參考,不一定能成為您想要的結果。以下是Java接口中盡可能防止應用數組正文


 假如你發明在一個接口應用有以下界說辦法:
 

public String[] getParameters();

那末你應當賣力反思。數組不只僅老式,並且我們有公道的來由防止裸露它們。在這篇文章中,我將試圖總結在Java API中應用數組的缺點。起首從最出人意表的一個例子開端。
數組招致機能欠安

你能夠以為應用數組是最疾速的,由於數組是年夜多半collection完成的底層數據構造。應用一個純數組怎樣會比應用一個包括數組的對象機能更低?


讓我們先從這個看起來很熟習的廣泛的習氣用法開端:
 

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

這個辦法從一個用來在其外部保留數據的可變聚集處創立了一個數據. 它經由過程供給一個確實年夜小的數組來測驗考試優化數組的創立. 風趣的是,這一“優化”使得其比上面的更簡略的版本速度還要慢(請看圖表中綠色VS橘色條):
 

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

不外,假如辦法前往的是一個List, 創立進攻式的正本又加倍的快了 (紅條):
 

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

分歧的地方在於一個ArrayList將它的數據項放在一個Object[]數組中,而且應用的是無類型的toArray辦法,其比有類型的辦法要快許多(藍條). 這是類型平安的,由於無類型的數組時封裝在由編譯器檢討的泛型類型ArrayList<T>中的.

這個圖標展現了一個在Java 7上n=5的參考尺度. 不外,更多的數據項或許是別的一個VM情形系啊,這幅圖片其實不會轉變太多. CPU的開支能夠其實不會太激烈,然則會有增加. 機遇有一個數組的應用者應當將其轉換到一個聚集中去,以方便用它做任何工作, 然後將成果轉換回一個數組,來送進別的一個接口的辦法中,諸如斯類做法.

是用一個簡略的ArrayList,而不是一個數組來晉升機能,無需再動太多的四肢舉動. ArrayList 為封裝的數組增長了32字節的恆定開支. 例如,一個有十個對象的數組須要104字節,一個ArrayList 136字節.

應用 聚集,你乃至能夠決議前往外部列表的一個弗成修正的版本:
 

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

此操作會在固定的市價運轉,是以他比任何上述其它的辦法都要快許多(黃條). 其統一個進攻式的拷貝分歧。一個弗成修正的聚集將會在你的外部數據變更時隨著變更。假如變更產生了,客戶端會在迭代數據項時運轉到一個ConcurrentModificationException中. 可以以為它是一個蹩腳的設計,接口供給了一個在運轉時拋出一個UnsupportedOperationException. 不外,至多關於外部的應用,這個辦法關於一個進攻式的拷貝而言,會是一個高機能的選擇 - 一些弗成能應用數組完成的器械.

數組界說一個構造,而不是一個接口

Java 是一門面向對象的說話。面向對象的焦點概念就是供給一些辦法來拜訪和操作它們的數據,而不是直接對數據域停止操作. 這些辦法創立一個接口來描寫你可以在對象下面做的工作.

因為java曾經對機能做了設計,原生類型和數組曾經被融會進了類型體系當中. 對象可使用數組來在內容高效地存儲數據. 但是,即便經由過程數組來出現一個可變聚集的元素,它們也不會供給任何辦法來拜訪和操作這些元素. 現實上,除直接拜訪的調換元素以外,在數組上你沒有若干其它工作可以做. 數組乃至連toString 和 equals 都沒有一個成心義的完成, 而聚集卻有:
 

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

分歧於數組,聚集的 API 供給了很多有效的辦法來拜訪元素. 用戶可以檢討包括的元素,提取子列表或許盤算交集. 聚集可以向數據層添加特定的特征, 諸如線程平安,同時將完成道理堅持在外部可見.

經由過程應用一個數據,你界說了數據被保留在內存中的哪一個處所. 經由過程應用一個聚集,你界說了用戶可以在數據上做的操作.

數組不是類型平安的

假如你依附於編譯器檢討的類型平安,當心對象數組. 上面的代碼會在運轉時奔潰,然則編譯器找不出成績地點:

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

緣由是數組是“協變式”的, 好比,假如 T 是S 的一個子類型, 那末 T[] 就會是 S[] 的一個子類型. Joshua Bloch 在其著作 Effective Java 涵蓋了一切的實際, 每個Java開辟者必讀.

歸因於這個行動,裸露數組類型的接口許可前往聲明數組類型的一個子類型, 招致了一個奇異的運轉時異常.


Bloch 同時也說明說,數組與泛型類型不兼容. 由於數組會在運轉時強迫請求有類型信息,而泛型則會在編譯時被檢討,泛型類型不克不及被放到數組中.

  •     普通而言,數組和泛型不克不及很好的融會。假如你發明本身在融會它們而獲得了一個編譯時毛病或許正告,那你的第一反響應當是用list去調換數組.

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

數組底層的說話結構、它們會被用在完成中,然則它們不該該想其它的類裸露. 在一個接口辦法中應用數組違反了面向對象的准繩,它會招致背和的API,而且它也能夠給類型平安和機能形成短板.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved