您好,登錄后才能下訂單哦!
public <T> void show(T t) {
}
所謂泛型方法,就是在聲明方法時定義一個或多個類型形參。 泛型方法的用法格式如下:
修飾符<T, S> 返回值類型 方法名(形參列表){
方法體
}
注意要點:
class Demo{
public <T> T fun(T t){ // 可以接收任意類型的數據
return t ; // 直接把參數返回
}
};
public class GenericsDemo26{
public static void main(String args[]){
Demo d = new Demo() ; // 實例化Demo對象
String str = d.fun("湯姆") ; // 傳遞字符串
int i = d.fun(30) ; // 傳遞數字,自動裝箱
System.out.println(str) ; // 輸出內容
System.out.println(i) ; // 輸出內容
}
};
先來看一個案例
/**
* 泛型接口的定義格式: 修飾符 interface 接口名<數據類型> {}
*/
public interface Inter<T> {
public abstract void show(T t) ;
}
/**
* 子類是泛型類
*/
public class InterImpl<E> implements Inter<E> {
@Override
public void show(E t) {
System.out.println(t);
}
}
Inter<String> inter = new InterImpl<String>() ;
inter.show("hello") ;
然后看看源碼中泛型的使用,下面是JDK 1.5 以后,List接口,以及ArrayList類的代碼片段。
//定義接口時指定了一個類型形參,該形參名為E
public interface List<E> extends Collection<E> {
//在該接口里,E可以作為類型使用
public E get(int index) {}
public void add(E e) {}
}
//定義類時指定了一個類型形參,該形參名為E
public class ArrayList<E> extends AbstractList<E> implements List<E> {
//在該類里,E可以作為類型使用
public void set(E e) {
.......................
}
}
這就是泛型的實質:允許在定義接口、類時聲明類型形參,類型形參在整個接口、類體內可當成類型使用,幾乎所有可使用普通類型的地方都可以使用這種類型形參。
泛型類派生子類
public class A extends Container<K, V>{}
public class A extends Container<Integer, String>{}
public class A extends Container{}
定義一個容器類,存放鍵值對key-value,鍵值對的類型不確定,可以使用泛型來定義,分別指定為K和V。
public class Container<K, V> {
private K key;
private V value;
public Container(K k, V v) {
key = k;
value = v;
}
public K getkey() {
return key;
}
public V getValue() {
return value;
}
public void setKey() {
this.key = key;
}
public void setValue() {
this.value = value;
}
}
在使用Container類時,只需要指定K,V的具體類型即可,從而創建出邏輯上不同的Container實例,用來存放不同的數據類型。
public static void main(String[] args) {
Container<String,String> c1=new Container<String ,String>("name","hello");
Container<String,Integer> c2=new Container<String,Integer>("age",22);
Container<Double,Double> c3=new Container<Double,Double>(1.1,1.3);
System.out.println(c1.getKey() + " : " + c1.getValue());
System.out.println(c2.getKey() + " : " + c2.getValue());
System.out.println(c3.getKey() + " : " + c3.getValue());
}
在JDK 1.7 增加了泛型的“菱形”語法:Java允許在構造器后不需要帶完成的泛型信息,只要給出一對尖括號(<>)即可,Java可以推斷尖括號里應該是什么泛型信息。 如下所示:
Container<String,String> c1=new Container<>("name","hello");
Container<String,Integer> c2=new Container<>("age",22);
public class Person {
public <T> Person(T t) {
System.out.println(t);
}
}
public static void main(String[] args){
//隱式
new Person(22);
//顯示
new<String> Person("hello");
}
這里唯一需要特殊注明的就是:
如果構造器是泛型構造器,同時該類也是一個泛型類的情況下應該如何使用泛型構造器:因為泛型構造器可以顯式指定自己的類型參數(需要用到菱形,放在構造器之前),而泛型類自己的類型實參也需要指定(菱形放在構造器之后),這就同時出現了兩個菱形了,這就會有一些小問題,具體用法再這里總結一下。
以下面這個例子為代表
public class Person<E> {
public <T> Person(T t) {
System.out.println(t);
}
}
這種用法:Person<String> a = new <Integer>Person<>(15);這種語法不允許,會直接編譯報錯!
通配符的設計存在一定的場景,例如在使用泛型后,首先聲明了一個Animal的類,而后聲明了一個繼承Animal類的Cat類,顯然Cat類是Animal類的子類,但是List卻不是List的子類型,而在程序中往往需要表達這樣的邏輯關系。為了解決這種類似的場景,在泛型的參數類型的基礎上新增了通配符的用法。
上界通配符顧名思義,<? extends T>表示的是類型的上界【包含自身】,因此通配的參數化類型可能是T或T的子類。
它表示集合中的所有元素都是Animal類型或者其子類
List<? extends Animal>
這就是所謂的上限通配符,使用關鍵字extends來實現,實例化時,指定類型實參只能是extends后類型的子類或其本身。
//Cat是其子類
List<? extends Animal> list = new ArrayList<Cat>();
下界通配符<? super T>表示的是參數化類型是T的超類型(包含自身),層層至上,直至Object
它表示集合中的所有元素都是Cat類型或者其父類
List <? super Cat>
這就是所謂的下限通配符,使用關鍵字super來實現,實例化時,指定類型實參只能是extends后類型的子類或其本身。
例如:
//Shape是其父類
List<? super Cat> list = new ArrayList<Animal>();
當聲明泛型類的實例時,傳遞的類型參數必須是引用類型,不能使用基本類型
User<int,double> user=new User<>(1,10,0);
如何解決
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。