① java的Collection介面中的方法containAll()在定義泛型形參時,為什麼要使用通配符
importjava.util.ArrayList;
importjava.util.Collection;
publicclassTest{
publicstaticvoidmain(String[]args){
acceptList1(newArrayList<String>());
acceptList2(newArrayList<String>());
acceptList3(newArrayList<String>());
}
//第一種方法是不推薦的,因為在支持泛型的地方沒有指定泛型,會導致編譯警告
publicstaticvoidacceptList1(Collectionc){
}
//第二種方法,實際上就是接受任何種類的泛型,這正是該方法需要的
publicstaticvoidacceptList2(Collection<?>c){
}
//第三種方法,編譯警告,竟然不接受Object的子類
publicstaticvoidacceptList3(Collection<Object>c){
}
//其實第三種方法可以寫作Collection<?extendsObject>,但這是多此一舉
}
任何一本教科書上都會說明,Java的泛型是偽泛型,編譯後泛型信息會消除掉。
也就是所謂的泛型擦除,所以寫了泛型和沒寫泛型差不錯。
泛型只是一種語法糖,只是幫你存入時檢查類型,取出時強制轉型而已。
② java中什麼是泛型,怎麼用泛型
最簡單的運用:List<String> list = new ArrayList<String>();
這個是什麼意思?
意思就是list只裝String類型的數據,別的,裝不進去
然後你就會覺得這個好像有點封裝的意思,比如LIst<Student>,封裝學生類
所以,所謂泛型就是廣泛的數據類型,你可以把它理解成封裝
③ java泛型
java泛型是1.5引進的一個新概念.
本題對於"? super T"和"? extends T",我從書上摘個經典的例子給你看看,如果不能理解,那麼你就參考以下書籍慢慢體會,循序漸進!
"? super T"和"? extends T",都是java泛型通配符,而用法又有區別,
還有super 和extends 不是java類關系中的超類和繼承的意思,他是通配符的下限和上限限制.
下面看一個通配符得高級用法:
在這一部分,我們來考慮一些通配符得高級用法。我們已經看到了上限通配符在從一個數據結構中進行讀取的幾個例子。現在考慮相反的情況,一個只寫的數據結構。
介面Sink是這種情況的一個簡單例子。
interface Sink<T> {
void flush(T t);
}
我們可以想像他被如下面的代碼一樣使用。方法writeAll() 被設計來把集合coll的所有元素flush到sink snk,並且返回最後一個flush的元素。
public static <T> T writeAll(Collection<T> coll, Sink<T> snk) {
T last = null;
for (T t : coll) {
last = t;
snk.flush(last);
}
return last;
}
Sink<Object> s;
Collection<String> cs;
String str = writeAll(cs, s); // 非法的調用!!
像上面所寫,writeAll() 的調用是非法的,因為沒有有效的類型參數可以被推斷出來。String 或 Object都不是T的合適的類型,因為Collection的元素和 Sink的元素必須是同樣的類型。
我們可以解決這個問題,通過使用通配符來修改writeAll()的方法簽名,如下:
<T> T writeAll(Collection<? extends T> coll, Sink<T> snk) { … }
String str = writeAll(cs, s); //可以調用但是返回值類型錯誤
這個調用現在是合法的,但是賦值產生錯誤,因為推斷出的返回值類型是 Object因為T 匹配了Sink的類型,Object。
解決方案是使用一種我們還沒有見過的有限制的通配符:有下限的通配符。語法 ? super T 表示T的一個未知的父類(或者是T自己)。這跟我們用? extends T 表示T的一個未知的子類是對應的。
<T> T writeAll(Collection<T> coll, Sink<? super T> snk) { … }
String str = writeAll(cs, s); // YES!!!
使用這個語法,這個調用是合法的,推斷出來的T是String,正是我們想要的。
現在讓我們看一個更現實的例子。一個 java.util.TreeSet<E> 代表一個有序的元素是E類型的樹。創建一個TreeSet的一個方法是傳遞一個 Comparator 對象給構造函數。這個Comparator將會用來按照需要對TreeSet進行排序。
TreeSet(Comparator<E> c)
Comparator 介面是核心:
interface Comparator<T> { int compare(T fst, T snd); }
假定我們要創建一個 TreeSet<String> 並傳遞一個合適的 Comparator,我們需要傳一個能比較String的Comparator。這可以是一個 Comparator<String>,也可以是一個 Comparator<Object>。然而我們不能用Comparator<Object>來調用上面的構造函數。我們可以使用一個有下限的通配符來得到我們需要的靈活性:
TreeSet(Comparator<? super E> c)
這允許任何可用的Comparator被傳遞進去。
作為使用下限通配符最終的例子,讓我們來看看方法 Collections.max(),它返回一個集合中的最大的元素。
現在,為了讓max()能工作,傳進來的集合中的所有元素必須實現 Comparatable介面。而且,他們必須都能夠被彼此比較(all be comparable to each other)。第一個嘗試是:
public static <T extends Comparable<T>> T max(Collection<T> coll)
就是說,方法的參數是某一個能和自己進行比較的T的集合。這限制太嚴格了。
為什麼?考慮一個能和任何對象進行比較的類型:
class Foo implements Comparable<Object> {...} ...
Collection<Foo> cf = ...;
Collections.max(cf); // 應該能工作
cf 中的每個元素都可以和每個cf中的其他元素進行比較,因為每個這樣的元素都是一個Foo,它可以和任意的對象進行比較,也可以和另一個Foo進行比較。
但是,使用上面的方法簽名,我們發現這個調用被拒絕。推斷出來的類型必須是Foo,但是Foo沒有實現介面 Comparable<Foo>。
T 精確的(exactly)和自己能比較是不需要的。所需要的是 T能夠和它的父類中的一個進行比較,這導出:(註:Collections.max()的實際方法簽名更復雜,我們在第10部分再討論。)
public static <T extends Comparable<? super T>> T max(Collection<T> coll)
這個推論對大多數想讓 Comparable 對任意類型生效的用法中都有效:你總是應該使用 Comparable<? super T>。
總之,如果你有一個只使用類型參數T作為參數的API,它的使用應該利用下限通配符( ? super T )的好處。相反的,如果API只返回T,你應該使用上限通配符( ? extends T )來給你的客戶端更大的靈活性。
(原文:This reasoning applies to almost any usage of Comparable that is intended to work for arbitrary types: You always want to use Comparable<? super T>.
In general, if you have an API that only uses a type parameter T as an argument, its uses should take advantage of lower bounded wildcards (? super T). Conversely, if the API only returns T, you'll give your clients more flexibility by using upper bounded wildcards (? extends T). )。
如果你想比較深刻的了解java泛型那麼
建議你看看<Java1.5泛型指南>
中文鏈接地址:http://blog.csdn.net/explorers/archive/2005/08/15/454837.aspx#_Toc111865968
英文pdf格式地址:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
④ java泛型之泛型通配符具體是什麼作用
Java中不允許嵌套泛型的內層通配符?匹配一個具體的類型,因為這可能破壞類型安全。
這樣做是可以的:
List<?> list = new ArrayList<Integer>();
而這樣做是不可以的:
List<List<?>> list = new ArrayList<List<Integer>>();
⑤ java通配符類型
如果是類引入的通配符,那麼指的是」*「,
如:import java.util.*;表示的是引入util包下的所有類;
如果是查找的通配符,那麼指的是」*「,
如:*.java;表示的是查找後綴為java的所有文件;
如果是泛型中的通配符,那麼指的是」<T>「;
如:List<T> list = new ArayList<T>();表示定義了一個通配的list對象,可以代表任何對象的list。
⑥ java中E,T,的區別
java泛型中E和T是可以隨便起名的,只是大家習慣用E和T,一傳十十傳百大家一看到<E>和<T>就知道是泛型了,所以這只是習慣使然。比如:
是不影響運行的。
至於?,?是用於定義泛型的通配符和邊界,一般比較常見的是<? extends T>,可以參考一下這篇資料
⑦ java 集合中泛型通配符 用了之後就不能添加 元素了 為什麼
首先泛型是用來約束的(或者說是規范化),泛型的本質是參數化類型,不是用來通配的(這個說法也不完全對),這個概念一定不要混淆了。
你添加的元素是String類型的,那麼你的代碼就得這樣:
ArrayList<String>arr=newArrayList<String>();
或者:
List<String>arr=newArrayList<String>();//多態,推薦使用
再或者:
Listarr=newArrayList();
ArrayListarr=newArrList();//這兩種沒有用泛型,編譯器會提示警告
用上面1和2方式的話,你的arr集合就只能存放String類型對象,3沒有用泛型,什麼類型的對象都可以存放。只是取出來的時候,會要類型轉換,這個過程很容易出錯。
希望我的回答能對你有所幫助,榮幸之至。
⑧ 你真的了解JAVA中的泛型E、T、K、V嗎
Java 泛型(generics)是 JDK 5 中引入的一個新特性, 泛型提供了編譯時類型安全檢測機制,該機制允許開發者在編譯時檢測到非法的類型。泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。
但是如果換成其他的字母代替 T ,在可讀性上可能會弱一些。通常情況下,T,E,K,V,?是這樣約定的:?表示不確定的 java 類型。T (type) 表示具體的一個java類型。K V (key value) 分別代表java鍵值中的Key Value。E (element) 代表Element。