你应该更新的Java知识
原文鏈接:http://www.blogbus.com/dreamhead-logs/236028457.html
你應該更新的Java知識之常用程序庫(一)
你應該更新的Java知識之常用程序庫(二)
你應該更新的Java知識之構建工具
你應該更新的Java知識之Observer
你應該更新的Java知識之集合初始化
你應該更新的Java知識之集合操作
你應該更新的Java知識之惰性求值
你應該更新的Java知識之Optional
你應該更新的Java知識之Optional高級用法
在傳統的Java里,為了表示一個集合,我們常常會寫出這樣的代碼:
public class People {private List people;public void setPeople(List people) {this.people = people;}public List getPeople() {return this.people;}... }嚴格說來,這樣的代碼存在缺陷。雖然貌似List被封裝到People里,但實際上,這個List的引用卻暴露在外面,這個類的用戶可以輕松地拿到List的引用,隨意修改。所以,下面是一種更嚴謹的寫法:
public class People {private List people;public void setPeople(List people) {this.people.addAll(people);}@SuppressWarnings("unchecked")public List getPeople() {return (List)this.people.clone();} ... }這里的做法基本思路是,做一個副本,保證內部引用(這里的people)不會傳播到外面。但在實際編寫代碼的時候,大多數人都不會這么做,能否意識到這樣的問題只是一個方面,這樣的代碼寫起來,也要比原來的那種寫法麻煩得多。按照許多公司的做法,這種要求只能放到代碼規范里,但無論如何,在程序世界里,人為規定永遠是最容易忽略的約定。
不過,在真實世界中,即便是我們寫的只是上面的最簡單那種形式,卻很少出現問題。原因何在呢?因為大多數情況下,我們編寫這樣程序的時候,會有一種隱形的約定,這個“List”是不變的。我們設置(set)完這個List之后,基本上不會留著它的引用在做任何操作;而得到(get)它之后,也基本上不會去修改它。
在這種情況下,我們使用的實際上是一個不變的List。既然是一個不變的List,那不如就更直接地把它表現出來。
Guava為我們提供了不變集合的概念,對應著各種具體類型,有ImmutableList、ImmutableSet,還有ImmutableMap。從名字上,我們不難看出它們的用法。
Guava不變集合的做法并不是另起爐灶,而是遵循了Java已有集合框架的約定。比如,通過查閱文檔,我們不難發現,ImmutableList就是一個List,只不過使用這個“List”,只不過,當我們嘗試調用諸如add、set之類試圖修改集合的方法時,它會拋出異常。正是有了這樣的基礎,不變集合可以和很多已有的類庫、框架配合在一起。
有了這個基礎,我們把不變集合的概念應用于之前的代碼,它就是下面這個樣子:
public class People {private ImmutableList people;public void setPeople(ImmutableList people) {this.people = people;}public ImmutableList getPeople() {return this.people;} ... }這樣一來,代碼依然很簡單,但是,意義卻與從前完全不一樣了。我們不必再為可能存在的隱憂顧慮了:一旦元素放到集合里,就不可能修改它了,因為它是不可變的。
對于使用這段代碼的人來說,getter自不必說,如往常一樣使用,setter也不費力。只是當做字面量使用的集合,我們已經在《你應該更新的Java知識之集合初始化》中討論過了。如果要適配于現有程序庫,把一個已有的List轉成ImmutableList也不復雜,一個簡單的copyOf方法就可以實現:
List existingPeople = ... ImmutableList immutablePeople = copyOf(existingPeople);為了讓討論更完整,這里不得不提到另外一個不變接口的選擇:Iterable。它是從Java 5開始進入JDK的一個接口:
public interface Iterable {Iterator iterator(); }作為一個Java程序員,我們對Iterator簡直再熟悉不過了,有了Iterator,我們就可以遍歷一個集合。所以,在一些情況下,我們也可以使用Iterable表示一個不變集合。大多數Java已有的集合類都實現了這個接口。
既然它是JDK里的東西,為什么不把它優先推薦呢?原因有幾個。最重要的一個原因在于我們熟知的Iterator,它有一個方法叫做remove,可能大多數Java程序員已經習慣性地忽略了這個方法,但它就在哪里,它是一個可以“改變”集合的方法,所以,從語義上說,它不是一個很好的選擇。另外,從已有的代碼習慣來說,很多程序員還是很喜歡用List、Set作為接口,所以,ImmutableList從心理上來說,更接近已有的習慣。剩下的一個點似乎不那么重要,有些代碼真的需要使用到特定類型的接口。不過,就大多數代碼而言,我們只是要得到的一個集合,做一些操作,而這些操作我們在《你應該更新的Java知識之集合操作》中做了一些討論。
在函數式編程中,不變是提升程序穩定性一個很重要的概念。既然我們大多數情況下實際用到的是不變集合,那就不妨直接把它表現出來。
總結
以上是生活随笔為你收集整理的你应该更新的Java知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RecyclerView.Adapter
- 下一篇: Google Guava官方教程(中文版