泛型-通配符,受限泛型(上限和下限)


掌握通配符“?”的使用。

掌握受限泛型的設置。

掌握泛型與子類繼承的限制。

具體內容

1.1匹配任意類型的通配符

  在開發中對象的引用傳遞(向上向下傳遞)是最常見的,但是,在泛型的操作中,在進行引用傳遞的時候泛型類型必須匹配才可以傳遞,否則不能傳遞。

  例如,如下沒有進行泛型類型匹配,一個是String,一個是Object類型。

package Thread1;
class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){ // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<String> i = new Info<String>() ; // 使用String為泛型類型
        i.setVar("MLDN") ;                            // 設置內容
 fun(i) ;                    //把String泛型類型的i對象傳遞給Object泛型類型的temp。
    }
    public static void fun(Info<Object> temp){ // 接收Object泛型類型的Info對象
        System.out.println("內容:" + temp) ;
    }
};

  編譯發生錯誤。

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The method fun(Info<Object>) in the type demo1 is not applicable for the arguments (Info<String>)

    at Thread1.demo1.main(demo1.java:18)

  泛型對象進行引用傳遞的時候,類型必須一致,如果非要傳遞,則可以將fun方法中Info參數的泛型取消掉(變成 void fun(Info temp)。、

  以上確實改進了功能,但是似乎不是很妥當,畢竟之前指定過泛型。

  以上程序在fun()方法中使用"Info<?>"的代碼形式,表示可以使用任意的泛型類型對象,這樣的話fun()方法定義就合理了,但是使用以上方法也有需要注意的地方,

即:如果使用“?“接收泛型對象的時候,則不能設置被泛型指定的內容

class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo14{
    public static void main(String args[]){
        Info<String> i = new Info<String>() ;        // 使用String為泛型類型
        i.setVar("MLDN") ;                            // 設置內容
        fun(i) ;
    }
    public static void fun(Info<?> temp){        // 可以接收任意的泛型對象
        System.out.println("內容:" + temp) ;
    }
};

  如果使用”?“意味着可以接收任意的內容,但是此內容無法直接使得用”?“修飾的泛型的對象進行修改。如下就會出問題:

package Thread1;
class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<?> i = new Info<String>() ;        // 使用String為泛型類型
        i.setVar("MLDN") ; // 設置內容,這里會出錯,因為”?“通配符修飾的對象只能接收,不能修改,也就是不能設置。
    }
};

  運行結果:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The method setVar(capture#1-of ?) in the type Info<capture#1-of ?> is not applicable for the arguments (String)

    at Thread1.demo1.main(demo1.java:17)

  在使用”?“只能接收,不能修改。

1.2受限泛型

  之前設置泛型的時候,實際上是可以任意設置的,只要是類就可以設置。但是在JAVA的泛型中可以指定一個泛型的上限和下限。

  

設置上限

class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo17{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        // 聲明Integer的泛型對象
        Info<Float> i2 = new Info<Float>() ;            // 聲明Float的泛型對象
        i1.setVar(30) ;                                    // 設置整數,自動裝箱
        i2.setVar(30.1f) ;                                // 設置小數,自動裝箱
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? extends Number> temp){    // 只能接收Number及其Number的子類
        System.out.print(temp + "、") ;
    }
};

  運行成功。但是,如果傳人的泛型類型為String的話就不行,因為String不是Number子類。

  在類中使用泛型上限。

package Thread1;
class Info<T extends Number>{    // 此處泛型只能是數字類型
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        // 聲明Integer的泛型對象
    }
};

  如果在使用Info的時候設置成String類型,則編譯的時候將會出現錯誤(String不是Number子類):

設置下限

  

class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo21{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 聲明String的泛型對象
        Info<Object> i2 = new Info<Object>() ;        // 聲明Object的泛型對象
        i1.setVar("hello") ;
        i2.setVar(new Object()) ;
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? super String> temp){ // 只能接收String或Object類型的泛型,String類的父類只有Object類
        System.out.print(temp + "、") ;
    }
};

  Object類和String類都是String的父類,所有運行成功,但是如果此時用Integer則會出錯,因為integer並不是String父類。

1.3解釋:泛型與子類繼承的限制。

  一個類的子類可以通過對象多態性,為其父類實例化,但是在泛型操作中,子類的泛型類型是無法使用父類的泛型類型接收的。例如:Info<String>不能使用Info<Object>

接收。

  例如,以下肯定出錯。

class Info<T>{
    private T var ;        // 定義泛型變量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo23{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 泛型類型為String
        Info<Object> i2 = null ;
       i2 = i1 ;                  //這里因為對象泛型類型不同,而出錯。
    }
};

  Object肯定比String大。

總結

  1)使用?可以接收任意泛型對象。

  2)泛型的上限:?extends 類型。

  3)泛型的下限:?super 類型。相對了解一些就可。

  4)了解為什么泛型子類之間的繼承無法直接轉換的原因。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM