第二十七條:優先使用泛型方法

一、泛型方法的優點(一)

優點:泛型方法能夠推斷出輸入參數中的參數類型
例:
public <E> E getType(E type){
  return type;
}
//當使用該方法的時候,虛擬機能夠推斷出輸入的參數的類型是什麼,並返回該類型。
舉例:合併兩個Set列表,用原生類型方法與泛型方法比較
//原生類型方法
public Set union(Set set1,Set set2){
    Set set = mew HashSet(s1);
    set.addAll(set2);
    return set;
}
使用原生類型方法虛擬機會出現類型不安全的警告。
//泛型方法
public <E> Set<E> union(Set<E> set1,Set<E> set2){
  Set<E> set = new HashSet<E>(set1);
  set.addAll(set2);
  return set;
}  
//由於虛擬機能夠推斷出輸入參數的參數類型,所以E是已知的,不會出現類型不安全的警告。
使用:
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Set<String> firstSet = new HashSet<String>(
				Arrays.asList("Bady","Tim","Alice"));
		Set<String> secondSet = new HashSet<String>(
				Arrays.asList("Come","On","Go","With","Me"));
		Set<String> set = union(firstSet, secondSet);
		System.out.println(set);
	}

二、泛型的優點(二)

優點:能夠推斷出被賦值對象的類型參數。
例:泛型的靜態工廠方法
	public static void main(String[]args){
		HashMap<String, String> map = newHashMap();
	}
	//泛型方法
	public static <K,V> HashMap<K,V> newHashMap(){
		return new HashMap<K, V>();
	}
這就是虛擬機能夠根據被賦值對象的類型參數,推斷出K,V的值是String,String。這樣K,V就是已知類型。
我們以前寫含有泛型的容器的時候都是:
HashMap<String,String> hashMap = new HashMap<String,String>();
在new 的時候還需要再重寫一遍類型參數。一個兩個還好,當數量多的時候呢。
所以利用泛型的靜態工廠是一種方便的方法。

三、泛型的優點(三)

優點:能夠推斷出被賦值對象的類型。
是不是跟優點(二)有點像。不過這個是能夠推斷被賦值對象的類型,優點二則是推斷被賦值對象的類型參數,不要弄混了。
例:
在Android中聲明layout中的View到代碼中的時候,都要使用(View)findViewById(R.id.xxx);
就像這樣:Button btn = (Button)findViewById(R.id.xxx);每次有需要強制轉換是一種很繁瑣的事情。
我們可以這樣構建一個方法
	public void onCreate(Bundle bundle) {
		// TODO Auto-generated method stub
		Button btn = getViewById(R.id.xxx);
	}
        //泛型方法
<span style="white-space:pre">	@SuppressWarnings("unchecked")</span>
	public <VT> VT getViewById(int id){
		return (VT)findViewById(id);
	}
因爲虛擬機能夠推斷出被賦值對象的類型,也就是能夠推斷出VT爲Button類型。這樣VT就是確定的類型,就不會出現類型不安全的問題。這樣就能放心的消除警告了

注:優點(二)(三)方法使用的基礎,都是基於賦值給被賦值對象。如果沒有被賦值對象,直接調用方法會發生什麼情況呢?
就像這樣:
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setView(getViewById(R.id.main_tv));//報錯
    }

    //所有Button,等控件都是View的子類。
    //作用:將生成的View放入該方法中
    public void setView(View view){
        View myView = view;
    }


    public <VT> VT getViewById(int id){
        return (VT)findViewById(id);
    }
如果沒有被賦值對象,虛擬機就無法進行判斷,返回的類型就是Object,就是說getViewById()返回的是Object。
因爲Object != View 所以肯定會出錯

四、有限制的類型參數的特殊形式(遞歸的類型限制)
形式:<E extends Comparable<E>>
表述:可以與自身比較的E類
使用情形:一般用於Comparable類
例:求List容器中的最大值
	public <T extends Comparable<T>> T calculateMax(List<T> list){
		Iterator<T> iterator = list.iterator();
		T result = iterator.next();
		while (iterator.hasNext()){
			T t = iterator.next();
			//需要判斷大小
			if (result.compareTo(t) < 0){
				result = t;
			}
		}
		return result;
	}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章