- 下面是自定義泛型方法的練習:
package com.mari.generic; import java.util.ArrayList; import java.util.Collection; import java.util.Date; public class Main { public static void main(String[] args) { Object obj = "Mari"; String rctValue = autoConvert(obj); //編譯通過 copy1(new ArrayList<String>(), new String[10]); //編譯通過, //因為沒有指定返回值類型,這個時候取參數的交集, //即傳遞過來的參數Date和String被當成Object類型 //具體解釋看總結中的倒數第二條。 copy2(new Date[10], new String[10]); //編譯錯誤, //ArrayList<Date>將傳遞的類型直接指定為了Date類型,這個時候Date類型和String //就不是同一種類型了,參數類型是具有傳遞性的, //所以編譯錯誤。具體的解釋可以看總結中最后一條。 copy2(new ArrayList<Date>(), new String[10]); } // 自動將Object類型的對象轉換成指定接收的類型 public static <T> T autoConvert(Object obj) { return (T) obj; } // 將任意類型的數據填充為相應類型的某個對象 public static <T> void fillArray(T[] array, T t) { int len = array.length; for (int i = 0; i < len; i++) { array[i] = t; } } // 采用自定義泛型的方法打印出任意參數化類型集合眾的所有內容 public static <T> void printCollection(Collection<T> collection, T obj) { collection.add(obj); for (T t : collection) { System.out.println(t); } } // 把任意參數類型集合中德數據安全的復制到相應的數組中 public static <T> void copy1(Collection<T> src, T[] dest) { } // 把任意參數類型數組中的數據安全的復制到相應的數組中 public static <T> void copy2(T[] src, T[] dest) { } }
總結:
- 編譯起判斷泛型方法的實際類型參數的過程稱為類型推斷,類型推斷是相對於知覺推斷的,其實現方法是一個非常復雜的過程。
- 根據調用泛型方法時實際傳遞的參數類型或返回值的類型來推斷,具體的規則如下:
- 當某個類型變量只在整個參數列表中所有參數和返回值中的一處被應用了,那么根據調用方法時該處的實際應用類型來確定,這很容易憑着感覺推斷出來,即根據調用方法時傳遞的剎那書類型或返回值來決定泛型參數的類型,例如:
swap(new String[3],3,4) -> static <E> swap(E[]a,int i, int j)
- 當某個類型變量在整個參數列表中的所有參數和返回值中多處被應用了,如果調用方法時這多處的實際應用類型都對應用一個類型來確定,這很容易憑着感覺推斷出來,例如
add(3,5) -> static <T> (T a, T b)
- 當某個類型變量在整個參數列表中的所有參數和返回值中的多處被應用了,如果調用方法時這多處的實際應用類型對應到了不同的類型,且沒有返回值,這個時候取多個最大交集類型,例如, 下面的語句實際對應的類型就是Number了,編譯沒有問題,只是運行時出了問題:
fill(new Integer[3], 3.5f) -> static <T> void fill(T[] a, T b)
-
當某個類型變量在整個參數列表中的所有參數和返回值多處被應用了,如果調用方法時這多處的實際應用類型對應到了不同的類型,並且使用了返回值,這時候優先考慮返回值的類型,例如,下面的語句實際對應的類型就是Integer了,編譯將報告錯誤,將變量x的類型改為float,對比eclipse報告的錯誤提示,接着再將x類型修改為Number,則沒有了錯誤:
int x =(3, 3.5f) -> static <T> T add(T a, T b)
-
參數類型的類型推斷具有傳遞性,下面第一種情況推斷實際參數為Object,編譯沒有問題,而第二種情況則根據參數化的ArrayList類實例將類型變量直接確定為Date類型,編譯將不能通過:
copy(new Integer[5],new String[5]) -> static <T> void copy(T[] a, T[] b)
其實如果大家上面的總結不太理解也沒有關系,大家只需要知道在使用自定義泛型的時候只需要在返回值的前面加上一個 <> 符號即可,簡單吧?
有什么問題歡迎大家留言,我會盡力為大家解答
下一篇的內容就是自定義泛型類的學習,敬請期待吧