1.什么是泛型,泛型有什么用,為什么要用
1.1 泛型就是一種未知的類,將未知的類型聲明在集合、對象上,泛型的默認類型為Object。
例如: ArrayList<String> str = new ArrayList<String>();
這是將String類型指定在str這個集合內,這個集合存儲或者讀取的類型只能為String類型。
1.2 使用泛型可以在傳參的時候(使用占位符 ? 占位)不固定傳入什么類型,即可通用類型,
如果不設置泛型的上限(例如:< ? extends List>)和下限(例如:<? super List>)。
1.3 使用泛型后對象或者集合內只能放入指定的數據類型,可以保證對象或者集合的安全性,減少類型的轉換操作。
2.怎么使用泛型,泛型可以作用在什么位置
2.1 有以下幾種使用場景以及放在那種位置
泛型只能定義引用數據類型,而不能使用基本數據類型
泛型類、泛型方法、泛型接口、泛型通配符
例如:作用在類上時( public class Animal <E> { E pet; } ) , 泛型跟在類后邊,可以指定用了泛型的類內部的 pet 的類型。
作用在對象上時( Animal<Dog> str = new Animal<Dog>(); ) , 泛型跟在類后邊 , 使得對象類的的 pet 屬性為 Dog類型。
作用在方法上時( public <E> Animal<E> getPet(){ return E ; } ), 如在類上沒有聲明泛型時,必須在返回值和訪問修飾符之間聲明。
作為方法入參時( public <E> void setPet(E pet){ this.pet = pet ; } ), 如在類上沒有聲明泛型時,必須在返回值和訪問修飾符之間聲明。
3.使用泛型的好處
3.1 使用泛型后對象或者集合內只能放入指定的數據類型,避免出現對象或者集合內的對象在多態使用的時候出現類型轉換異常(java.lang.ClassCastException),可以保證對象或者集合的安全性。
3.2 指定了類型后,對象、集合或方法內只能使用對應的類型,可以減少類型的轉換操作(在沒有指定類型是類型轉換必須使用 instanceof 關鍵字來進行判定),縮減了代碼了,方便了程序員。
下面以代碼的形式講解
聲明在類上時,寫在類名后邊
package com.jq;
/**
* 聲明在類上時,寫在類名后邊
* @param <E>
*/
class Animal <E> {
/**
* 作為屬性聲明時,必須在類上聲明泛型
*/
E pet;
/**
* 作為參數或者返回值時,如果在類上沒有聲明,必須在訪問修飾符和返回值之間
* @param pet
*/
public void setPet(E pet){
this.pet = pet;
}
public E getPet(){
return pet;
}
public <T> void call(T t){
System.out.println( t.toString() );
}
}
使用泛型實現時,實現類必須使用對應的泛型類。
實現類聲明泛型跟接口指定泛型可以同時使用。
package com.jq;
/**
* 作用在接口上,如果實現該接口時指定實現類型
* @param <T>
*/
public interface Animals<T>{
void call(T t);
}
/**
* 拉布拉多犬
*/
/**
* 使用泛型實現時,實現類必須使用對應的泛型類。
* 實現類聲明泛型跟接口指定泛型可以同時使用。
*如下代碼:
*/
class LaBuLaDuo<T> implements Animals<String> {
public void call(String s) {
System.out.println( s );
}
}
泛型占位符 ? 的使用
如何設置泛型的上限下限
package com.jq;
/**
* 小狗狗
*/
class Dog extends Animal {
public String name;
public Integer age;
}
/**
* 泛型占位符 ? 的使用
* 泛型的上限 < ? extends E> 即傳入參數必須為E 的子類
* 泛型的下限 < ? super E>
*/
public class ErHa <E> {
//當參數傳遞時可以設置上下限 比如下面的是 傳入類型必須是 Dog 的子類,上限為Dog
public void call(Animal< ? extends E> s){
System.out.println(s.pet);
}
//傳入類型必須是 Dog 的父類,下限為Dog
public void jump(Animal< ? super E> s){
System.out.println(s.pet);
}
// ? 占位符單獨使用時,相當於 < ? extends Object >
public void smile(Animal<?> s){
System.out.println(s.pet);
}
public static void main(String[] args) {
new ErHa<Dog>().call(new Dog());
}
}