『壹』 java中如何實現泛型類和泛型類之間的繼承
A1的泛型參數要有兩個,否則無法確定抽象父類的泛型。
public class inher
{
public static void main(String[] args)
{
var a1 = new A1<Child, Parent>();
a1.a = new Parent();
a1.b = new Child();
a1.a.parent = 1;
a1.b.child = 2;
System.out.println(a1.a.parent);
System.out.println(a1.b.child);
}
}
abstract class A<T>
{
public T a;
}
class A1<U extends T, T> extends A<T>
{
public U b;
}
class Parent
{
public int parent;
}
class Child extends Parent
{
public int child;
}
『貳』 java <A extends Annotation> 中 A 是什麼泛型,A不是對象
A應該是註解的Class;
對比參照以下信息:
1. Class有一個方法:isAnnotationPresent(Class<? extends Annotation> anno)
是用來判斷anno是不是代表註解的,參數的泛型使用了extends,但anno是定義的註解的Class,並不是Annotation的子類或介面實現類,這也可以通過Class類方法isAssignableFrom(Class<?> cls)來判斷.說明註解並不是Annotation的子類或實現類
2. Class還有兩個方法:isAnnotation()和isInterface(),如果用註解來判斷,這兩個返回值都是true,但由1知道註解不是Annotation的子類,從表面看這就有問題了,為什麼註解是Annotation卻不是其子類呢?從isAnnotation()的解釋可以得到答案:Returns true if this Class object represents an annotation type.這里使用了represents而不是extends
3. 從1和2的分析,問題就回到了泛型中extends的含義了,? extends不一定表示繼承的子類或介面實現類!!
『叄』 java 泛型extends為什麼不能寫
因為范圍過小。
_紫齲頤且酪壞悖魏蔚姆盒捅淞浚ū熱繒飫鐧_)都是派生自Object,所以我們在填充泛型變數時,只能使用派生自Object的類,比如String,Integer,Double,等而不能使用原始的變數類型,比如int,double,float等。
『肆』 JAVA中的泛型類是什麼東西
在Java SE1.5之前,沒有泛型的情況的下,通過對類型Object的引用來實現參數的「任意化」,「任意化」帶來的缺點是要做顯式的強制類型轉換,而這種轉換是要求開發者對實際參數類型可以預知的情況下進行的。對於強制類型轉換錯誤的情況,編譯器可能不提示錯誤,在運行的時候才出現異常,這是一個安全隱患。 1、泛型的類型參數只能是類類型(包括自定義類),不能是簡單類型。2、同一種泛型可以對應多個版本(因為參數類型是不確定的),不同版本的泛型類實例是不兼容的。3、泛型的類型參數可以有多個。4、泛型的參數類型可以使用extends語句,例如<Textends superclass>。習慣上成為「有界類型」。5、泛型的參數類型還可以是通配符類型。例如Class<?> classType =Class.forName(java.lang.String);
『伍』 java 如何繼承泛型
下面一個子類繼承泛型父類的例子,可以參考一下:
//父類是一個泛型
classParent<T>{
privateTval;
publicTgetVal(){
returnval;
}
publicvoidsetVal(Tval){
this.val=val;
}
}
classChild1extendsParent<Integer>{
}
classChild2extendsParent<String>{
}
publicclassApp{
publicstaticvoidmain(String[]argv){
Child1c1=newChild1();
c1.setVal(123456);
System.out.println(c1.getVal());
Child2c2=newChild2();
c2.setVal("abcdef");
System.out.println(c2.getVal());
}
}
『陸』 Java 泛型 lt;super T>中 super 怎麼 理解與 extends 有何不同
java泛型是1.5引進的一個新概念.本題對於"?superT"和"?extendsT",我從書上摘個經典的例子給你看看,如果不能理解,那麼你就參考以下書籍慢慢體會,循序漸進!"?superT"和"?extendsT",都是java泛型通配符,而用法又有區別,還有super和extends不是java類關系中的超類和繼承的意思,他是通配符的下限和上限限制.下面看一個通配符得高級用法:在這一部分,我們來考慮一些通配符得高級用法。我們已經看到了上限通配符在從一個數據結構中進行讀取的幾個例子。現在考慮相反的情況,一個只寫的數據結構。介面Sink是這種情況的一個簡單例子。interfaceSink{voidflush(Tt);}我們可以想像他被如下面的代碼一樣使用。方法writeAll()被設計來把集合coll的所有元素flush到sinksnk,並且返回最後一個flush的元素。publicstaticTwriteAll(Collectioncoll,Sinksnk){Tlast=null;for(Tt:coll){last=t;snk.flush(last);}returnlast;}Sinks;Collectioncs;Stringstr=writeAll(cs,s);//非法的調用!!像上面所寫,writeAll()的調用是非法的,因為沒有有效的類型參數可以被推斷出來。String或Object都不是T的合適的類型,因為Collection的元素和Sink的元素必須是同樣的類型。我們可以解決這個問題,通過使用通配符來修改writeAll()的方法簽名,如下:TwriteAll(Collectioncoll,Sinksnk){…}Stringstr=writeAll(cs,s);//可以調用但是返回值類型錯誤這個調用現在是合法的,但是賦值產生錯誤,因為推斷出的返回值類型是Object因為T匹配了Sink的類型,Object。解決方案是使用一種我們還沒有見過的有限制的通配符:有下限的通配符。語法?superT表示T的一個未知的父類(或者是T自己)。這跟我們用?extendsT表示T的一個未知的子類是對應的。TwriteAll(Collectioncoll,Sinksnk){…}Stringstr=writeAll(cs,s);//YES!!!使用這個語法,這個調用是合法的,推斷出來的T是String,正是我們想要的。現在讓我們看一個更現實的例子。一個java.util.TreeSet代表一個有序的元素是E類型的樹。創建一個TreeSet的一個方法是傳遞一個Comparator對象給構造函數。這個Comparator將會用來按照需要對TreeSet進行排序。TreeSet(Comparatorc)Comparator介面是核心:interfaceComparator{intcompare(Tfst,Tsnd);}假定我們要創建一個TreeSet並傳遞一個合適的Comparator,我們需要傳一個能比較String的Comparator。這可以是一個Comparator,也可以是一個Comparator。然而我們不能用Comparator來調用上面的構造函數。我們可以使用一個有下限的通配符來得到我們需要的靈活性:TreeSet(Comparatorc)這允許任何可用的Comparator被傳遞進去。作為使用下限通配符最終的例子,讓我們來看看方法Collections.max(),它返回一個集合中的最大的元素。現在,為了讓max()能工作,傳進來的集合中的所有元素必須實現Comparatable介面。而且,他們必須都能夠被彼此比較(allbecomparabletoeachother)。第一個嘗試是:publicstatic>Tmax(Collectioncoll)就是說,方法的參數是某一個能和自己進行比較的T的集合。這限制太嚴格了。為什麼?考慮一個能和任何對象進行比較的類型:classFooimplementsComparable{}Collectioncf=;Collections.max(cf);//應該能工作cf中的每個元素都可以和每個cf中的其他元素進行比較,因為每個這樣的元素都是一個Foo,它可以和任意的對象進行比較,也可以和另一個Foo進行比較。但是,使用上面的方法簽名,我們發現這個調用被拒絕。推斷出來的類型必須是Foo,但是Foo沒有實現介面Comparable。T精確的(exactly)和自己能比較是不需要的。所需要的是T能夠和它的父類中的一個進行比較,這導出:(註:Collections.max()的實際方法簽名更復雜,我們在第10部分再討論。)publicstatic>Tmax(Collectioncoll)這個推論對大多數想讓Comparable對任意類型生效的用法中都有效:你總是應該使用Comparable。總之,如果你有一個只使用類型參數T作為參數的API,它的使用應該利用下限通配符(?superT)的好處。相反的,如果API只返回T,你應該使用上限通配符(?extendsT)來給你的客戶端更大的靈活性。(原文:rarbitrarytypes:YoualwayswanttouseComparable.Ingeneral,,(?superT).Conversely,iftheAPIonlyreturnsT,you'(?extendsT).)。
『柒』 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泛型的高級應用
在上面的例子中,由於沒有限制class GenericsFoo<T>類型持有者T的范圍,實際上這里的限定類型相當於Object,這和「Object泛型」實質是一樣的。限制比如我們要限制T為集合介面類型。只需要這么做:
class GenericsFoo<T extends Collection>,這樣類中的泛型T只能是Collection介面的實現類,傳入非Collection介面編譯會出錯。
注意:<T extends Collection>這里的限定使用關鍵字extends,後面可以是類也可以是介面。但這里的extends已經不是繼承的含義了,應該理解為T類型是實現Collection介面的類型,或者T是繼承了XX類的類型。
下面繼續對上面的例子改進,我只要實現了集合介面的類型: publicclassCollectionGenFoo<TextendsCollection>{privateTx;publicCollectionGenFoo(Tx){this.x=x;}publicTgetX(){returnx;}publicvoidsetX(Tx){this.x=x;}}實例化的時候可以這么寫: {publicstaticvoidmain(Stringargs[]){CollectionGenFoo<ArrayList>listFoo=null;listFoo=newCollectionGenFoo<ArrayList>(newArrayList());//出錯了,不讓這么干。//原來作者寫的這個地方有誤,需要將listFoo改為listFoo1//需要將CollectionGenFoo<Collection>改為CollectionGenFoo<ArrayList>//CollectionGenFoo<Collection>listFoo1=null;//listFoo1=newCollectionGenFoo<ArrayList>(newArrayList());System.out.println("實例化成功!");}}當前看到的這個寫法是可以編譯通過,並運行成功。可是注釋掉的兩行加上就出錯了,因為<T extends Collection>這么定義類型的時候,就限定了構造此類實例的時候T是確定的一個類型,這個類型實現了Collection介面,但是實現 Collection介面的類很多很多,如果針對每一種都要寫出具體的子類類型,那也太麻煩了,我乾脆還不如用Object通用一下。別急,泛型針對這種情況還有更好的解決方案,那就是「通配符泛型」。 雖然Java泛型簡單的用 extends 統一的表示了原有的 extends 和 implements 的概念,但仍要遵循應用的體系,Java 只能繼承一個類,但可以實現多個介面,所以你的某個類型需要用 extends 限定,且有多種類型的時候,只能存在一個是類,並且類寫在第一位,介面列在後面,也就是:
<T extends SomeClass & interface1 & interface2 & interface3>
這里的例子僅演示了泛型方法的類型限定,對於泛型類中類型參數的限制用完全一樣的規則,只是加在類聲明的頭部,如: publicclassDemo<TextendsComparable&Serializable>{//T類型就可以用Comparable聲明的方法和Seriablizable所擁有的特性了} 為了解決類型被限制死了不能動態根據實例來確定的缺點,引入了「通配符泛型」,針對上面的例子,使用通配泛型格式為<? extends Collection>,「?」代表未知類型,這個類型是實現Collection介面。那麼上面實現的方式可以寫為: {publicstaticvoidmain(Stringargs[]){CollectionGenFoo<ArrayList>listFoo=null;listFoo=newCollectionGenFoo<ArrayList>(newArrayList());//出錯了,不讓這么干。//原來作者寫的這個地方有誤,需要將listFoo改為listFoo1//CollectionGenFoo<Collection>listFoo1=null;//listFoo1=newCollectionGenFoo<ArrayList>(newArrayList());System.out.println("實例化成功!");}}注意:
1、如果只指定了<?>,而沒有extends,則默認是允許Object及其下的任何Java類了。也就是任意類。
2、通配符泛型不單可以向下限制,如<? extends Collection>,還可以向上限制,如<? super Double>,表示類型只能接受Double及其上層父類類型,如Number、Object類型的實例。
3、泛型類定義可以有多個泛型參數,中間用逗號隔開,還可以定義泛型介面,泛型方法。這些都與泛型類中泛型的使用規則類似。