今天閱讀源碼的時候,無意中看到了Collections.unmodifiableList的用法,因為以前沒有這樣做過,所以查詢了他的API,是這樣寫的
public static <T> List<T> unmodifiableList(List<? extends T> list)
參數:list--這是一個不可修改視圖是要返回的列表中。
返回值:在方法調用返回指定列表的不可修改視圖。
1、用法探討:
1 public class CollectionsListDemo { 2 public static void main(String[] args) { 3 4 List<String> list = new ArrayList<String>(); 5 list.add("aa"); 6 list.add("bb"); 7 8 System.out.println("初始化前: "+ list); 9 10 //實現 unmodifiable 11 List<Character> immutablelist = Collections.unmodifiableList(list); 12 13 //修改 list 14 immutablelist.add("zz"); 15 }} 16 17 結果: 18 19 初始化前:: [aa, bb] 20 21 Exception in thread "main" java.lang.UnsupportedOperationException
2、繼續追蹤,到底什么場景遇到呢?重構是怎么寫的的?
在《重構——改善既有代碼的設計》一書中,有一種重構手法叫Encapsulate Collection ,(封裝集合),
定義是:讓函數返回這個集合的副本,並在這個類中提供添加/移除集合的副本
為了演示該重構手法
這本書介紹的是:我們經常用集合,Collection,可能是Array,ArrayList,set,vector保存一組實例,這樣的類通常也會提供針對該集合的取值與設值函數
但是集合的處理方式和其他種類略有不同,取值函數不應該返回集合本身,因為這會讓用戶得以修改集合的內容而集合擁有者去一無所知,這樣會對用戶暴露過多的對象的內部結構信息。如果一個取值函數確實要返回多個值,他應該避免用戶直接操作對象內保存的集合,並隱藏對象內與用戶無關的的數據結構
此外,不應該為這個集合提供一個設置函數,但是應該提供對象內集合本身添加/刪除的函數,這樣,集合擁有者(對象)就可以控制集合元素的添加與刪除
如果做到了上邊的一點,集合就很好的封裝起來,這樣就降低了集合擁有者和用戶之間的耦合度
常用到的做法:
(1)加入為集合添加/移除元素的函數
(2)將保存的集合的字段初始化一個空的集合
3、下面對上邊的內容的例子介紹:
原來我這樣寫的:
1 import java.util.List; 2 3 public class Student 4 { 5 private String userName ; 6 7 private List<String> courses ; 8 9 10 public Student (String userName , List<String> courses) 11 { 12 this.userName = userName; 13 this.courses = courses; 14 } 15 16 public String getUserName() 17 { 18 return userName ; 19 } 20 21 public void setUserName(String userName) 22 { 23 this.userName = userName; 24 } 25 26 public List<String> getCourses() 27 { 28 return courses ; 29 } 30 31 public void setCourses(List<String> courses) 32 { 33 this.courses = courses; 34 } 35 36 37 38 }
重構后,按照上面介紹的原則,這樣重構:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 5 public class Student 6 { 7 private String userName ; 8 9 private List<String> courses ; 10 11 public Student (String userName , List<String> courses) 12 { 13 this.userName = userName; 14 this.courses = courses; 15 } 16 17 public String getUserName() 18 { 19 return userName ; 20 } 21 22 public void setUserName(String userName) 23 { 24 this.userName = userName; 25 } 26 27 public void addCourse(String course) 28 { 29 courses.add(course); 30 } 31 32 public boolean removeCourse(String course) 33 { 34 return courses .remove(courses ); 35 36 } 37 38 public List<String> getCourses() 39 { 40 return Collections.unmodifiableList( courses); 41 } 42 43 public static void main(String[] args) 44 { 45 List<String> list = new ArrayList<String>(); 46 list.add( "數學"); 47 list.add( "語文"); 48 Student s = new Student("lily" , list); 49 50 List<String> anotherList = s.getCourses(); 51 52 /** 53 * throws java.lang.UnsupportedOperationException should replace with 54 * s.addCourse(String course) 55 */ 56 anotherList.add( "英語"); 57 58 // 不會走到這一步,因為上邊拋出了異常 59 System. out.println("lily's course.length = " + s.getCourses().size()); 60 } 61 62 }
4、總結
使用這種方法重構的意義:就好比我們網上購物一樣,你可以往購物車添加自己想買的東西,但是商戶不能在不通知顧客(我們)的情況下,就任意的添加商品,並修改商品的價格等,入口只能是一個,也就是在顧客手中。比喻可能不是很恰當,反正意思大概就是這樣。