Java泛型全解析

把一個對象放進集合中以後,集合就會忘記這個對象的數據類型,當再次取出該對象時,該對象的編譯類型就變成Object類型了java

 

爲了解決上面的問題,就引出了泛型這一個概念ide

 

泛型接口和類

public class Fruit<T> {ui

private T info;this

 

public Fruit(T info) {spa

this.info = info;對象

}接口

 

public T getInfo() {內存

return info;get

}it

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<String>("蘋果");

System.out.println(lt.getInfo());

Fruit<Integer> intg = new Fruit<Integer>(1);

System.out.println(intg.getInfo());

}

}

 

能夠靈活的封裝,而且同時有能夠限定類型,泛型的接口和類更像是一種通用的模型,模型內部的類型由使用者本身限定

不管爲泛型的類型形參傳入哪種類型的實參,對於Java來講,他們依然被當成同一個類處理,在內存中也只佔用一塊內存空間,所以在靜態方法、靜態初始化塊或者靜態變量的聲明和初始化中不容許使用類型形參

 

泛型接口和類的子類

 

public class Apple extends Fruit<String>{

 

public Apple(String info) {

super(info);

}

 

@Override

public String getInfo() {

return super.getInfo();

}

 

}

 

  • 使用泛型接口或類的時候,雖然能夠不加<>部分,可是推薦加上,否則還要強制類型轉換等麻煩操做

  • 重寫父類方法或者實現接口的時候,返回值必定要跟父類(接口)一致

 

設定類型形參的上限

 

public class Fruit<T extends String & java.io.Serializable> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

 

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<>("蘋果");

System.out.println(lt.getInfo());

Fruit<?> intg = new Fruit<>("1");

System.out.println(intg.getInfo());

}

}

 

  • 能夠有多個限定條件,存在多個限定條件的時候,使用&鏈接

  • 至多一個父類上限,多個接口上限

  • 接口上限要在類上線後面

 

類型通配符

 

使用類型通配符的類是各類該類的泛型的父類

 

public class Fruit<T> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

 

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<>("蘋果");

System.out.println(lt.getInfo());

Fruit<?> intg = new Fruit<>(1);

System.out.println(intg.getInfo());

}

}

 

  • 在Java 7之後可使用菱形語法,在構造器後不須要完整的泛型信息

  • ?」用於操做具體的某個泛型類的時候,還未肯定最終使用時,採用的對象類型,就用問號做爲佔位的含義

 

通配符的上限設定

 

Fruit<? extends String> intg = new Fruit<>("1");

 

  • 使用extends的方式限定?必須是String類型或者是其子類類型

 

通配符的下限設定

 

static <T,B> void getCollection(Fruit<? super T>b){

System.out.println(b);

}

 

  • 必定要是T或者T的父類

 

泛型方法

 

修飾符<T,S>返回值類型 方法名(形參列表){

 

方法體

 

}

 

static <T,B> void getCollection(B[]b,Collection<T> c){

 

}

 

  • 多個類型形參之間用逗號分隔

  • 全部類型形參聲明放在修飾符和方法返回類型之間

  • 方法中定義的類型形參只能在該方法裏使用,而接口或類中定義的類型形參能夠在整個接口、類中使用

  • 方法中的泛型參數無需顯式傳入實際類型參數

 

public class Fruit<T extends String & java.io.Serializable> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

static <T,B> void getCollection(B[]b){

System.out.println(b);

}

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit.getCollection(new String[]{"1"});

}

}

 

  • 存在泛型構造器,不能使用」菱形「語法

 

泛型方法與類型通配符的區別

 

  • 泛型方法容許類型形參被用來表示方法的一個或多個參數之間的類型依賴關係,或者方法返回值與參數之間的類型依賴關係,若是沒有這樣的類型依賴關係,就不該該使用泛型方法

  • 類型通配符既能夠在方法簽名中定義形參的類型,也能夠用於定義變量類型,但泛型方法中的類型形參必須在對應方法中顯式聲明

 

擦除和轉換

 

擦除

 

當把一個具備泛型信息的對象賦值給另外一個沒有泛型信息的變量時,尖括號中的泛型信息就會被擦除扔掉

 

轉換

 

當把一個沒有泛型信息的對象賦值給另外一個泛型信息的變量時,不會發生報錯,會自動轉換

相關文章
相關標籤/搜索