欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳談Java泛型中T和問(wèn)號(hào)(通配符)的區(qū)別

 更新時(shí)間:2017年10月30日 09:54:44   作者:ikownyou  
下面小編就為大家?guī)?lái)一篇詳談Java泛型中T和問(wèn)號(hào)(通配符)的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

類(lèi)型本來(lái)有:簡(jiǎn)單類(lèi)型和復(fù)雜類(lèi)型,引入泛型后把復(fù)雜類(lèi)型分的更細(xì)了.

概述

泛型是Java SE 1.5的新特性,泛型的本質(zhì)是參數(shù)化類(lèi)型,也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù)。這種參數(shù)類(lèi)型可以用在類(lèi)、接口和方法的創(chuàng)建中,分別稱(chēng)為泛型類(lèi)、泛型接口、泛型方法。 Java語(yǔ)言引入泛型的好處是安全簡(jiǎn)單。

在Java SE 1.5之前,沒(méi)有泛型的情況的下,通過(guò)對(duì)類(lèi)型Object的引用來(lái)實(shí)現(xiàn)參數(shù)的“任意化”,“任意化”帶來(lái)的缺點(diǎn)是要做顯式的強(qiáng)制類(lèi)型轉(zhuǎn)換,而這種轉(zhuǎn)換是要求開(kāi)發(fā)者對(duì)實(shí)際參數(shù)類(lèi)型可以預(yù)知的情況下進(jìn)行的。對(duì)于強(qiáng)制類(lèi)型轉(zhuǎn)換錯(cuò)誤的情況,編譯器可能不提示錯(cuò)誤,在運(yùn)行的時(shí)候才出現(xiàn)異常,這是一個(gè)安全隱患。

泛型的好處是在編譯的時(shí)候檢查類(lèi)型安全,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的,以提高代碼的重用率。

泛型的規(guī)則限制

泛型的類(lèi)型參數(shù)只能是類(lèi)類(lèi)型(包括自定義類(lèi)),不能是簡(jiǎn)單類(lèi)型。

同一種泛型可以對(duì)應(yīng)多個(gè)版本(因?yàn)閰?shù)類(lèi)型是不確定的),不同版本的泛型類(lèi)實(shí)例是不兼容的。

泛型的類(lèi)型參數(shù)可以有多個(gè)。

泛型的參數(shù)類(lèi)型可以使用extends語(yǔ)句,例如。習(xí)慣上稱(chēng)為“有界類(lèi)型”。

泛型的參數(shù)類(lèi)型還可以是通配符類(lèi)型。例如Class<?> classType = Class.forName(“java.lang.String”);

1、具體例子

下面給出兩個(gè)簡(jiǎn)單的例子,實(shí)現(xiàn)同樣的功能,一個(gè)使用了泛型,一個(gè)沒(méi)有使用泛型。

例子一:使用了泛型

public class Gen<T> {

  private T t;

  public Gen(T t){
    this.t = t;
  }
  public T getT() {
    return t;
  }
  public void setT(T t) {
    this.t = t;
  }

  public void showType(){
    System.out.println("T的實(shí)際類(lèi)型是:" + t.getClass().getName());
  }

  public static void main(String[] args) {
    Gen<Integer> gen = new Gen<Integer>(1);
    gen.showType();

    int i = gen.getT(); 
    System.out.println(" value = " + i); 
    System.out.println(" ====================== "); 

    //定義泛型類(lèi)Gen的一個(gè)String的版本 
    Gen<String>strObj = new Gen<String>("Hello Gen!"); 
    strObj.showType(); 
    String s = strObj.getT(); 
    System.out.println(" value = " + s); 

  }
}

例子二:沒(méi)有使用泛型

public class Gen2 { 

  // 定義一個(gè)通用類(lèi)型成員 
  private Object obj; 

  public Gen2(Object obj) { 
    this.obj = obj; 
  } 

  public Object getObj() { 
    return obj; 
  } 

  public void setObj(Object obj) { 
    this.obj = obj; 
  } 

  public void showType() { 
    System.out.println("T的實(shí)際類(lèi)型是: " + obj.getClass().getName()); 
  } 

  public static void main(String[] args) { 
    // 定義類(lèi)Gen2的一個(gè)Integer版本 
    Gen2 intObj = new Gen2(2); 
    intObj.showType(); 

    int i = (Integer) intObj.getObj(); 
    System.out.println(" value = " + i); 
    System.out.println(" ====================== "); 

    // 定義類(lèi)Gen2的一個(gè)String版本 
    Gen2 strOb = new Gen2("Hello Gen!"); 
    strOb.showType(); 
    String s = (String) strOb.getObj(); 
    System.out.println(" value= " + s); 
  } 
} 

2、深入泛型

在Java 5之前,為了讓類(lèi)有通用性,往往將參數(shù)類(lèi)型、返回類(lèi)型設(shè)置為Object類(lèi)型,當(dāng)獲取這些返回類(lèi)型來(lái)使用時(shí)候,必須將其“強(qiáng)制”轉(zhuǎn)換為原有的類(lèi)型或者接口,然后才可以調(diào)用對(duì)象上的方法。

泛型和使用“Object泛型”方式實(shí)現(xiàn)結(jié)果的完全一樣,但是簡(jiǎn)單多了,因?yàn)椴恍枰獜?qiáng)制類(lèi)型轉(zhuǎn)換。

泛型類(lèi)語(yǔ)法:

使用來(lái)聲明一個(gè)類(lèi)型持有者名稱(chēng),然后就可以把T當(dāng)作一個(gè)類(lèi)型代表來(lái)聲明成員、參數(shù)和返回值類(lèi)型。當(dāng)然T僅僅是個(gè)名字,這個(gè)名字可以自行定義。

class GenericsFoo 聲明了一個(gè)泛型類(lèi),這個(gè)T沒(méi)有任何限制,實(shí)際上相當(dāng)于Object類(lèi)型,實(shí)際上相當(dāng)于 class GenericsFoo。

與Object泛型類(lèi)相比,使用泛型所定義的類(lèi)在聲明和構(gòu)造實(shí)例的時(shí)候,可以使用“<實(shí)際類(lèi)型>”來(lái)一并指定泛型類(lèi)型持有者的真實(shí)類(lèi)型。例如:

GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));

當(dāng)然,也可以在構(gòu)造對(duì)象的時(shí)候不使用尖括號(hào)指定泛型類(lèi)型的真實(shí)類(lèi)型,但是你在使用該對(duì)象的時(shí)候,就需要強(qiáng)制轉(zhuǎn)換了。比如:

GenericsFoo douFoo=new GenericsFoo(new Double("33"));

實(shí)際上,當(dāng)構(gòu)造對(duì)象時(shí)不指定類(lèi)型信息的時(shí)候,默認(rèn)會(huì)使用Object類(lèi)型,這也是要強(qiáng)制轉(zhuǎn)換的原因。

3、高級(jí)應(yīng)用

限制泛型

在上面的例子中,由于沒(méi)有限制class GenericsFoo類(lèi)型持有者T的范圍,實(shí)際上這里的限定類(lèi)型相當(dāng)于Object,這和“Object泛型”實(shí)質(zhì)是一樣的。限制比如我們要限制T為集合接口類(lèi)型。只需要這么做:
class GenericsFoo,這樣類(lèi)中的泛型T只能是Collection接口的實(shí)現(xiàn)類(lèi),傳入非Collection接口編譯會(huì)出錯(cuò)。

多接口限制

雖然Java泛型簡(jiǎn)單的用 extends 統(tǒng)一的表示了原有的 extends 和 implements 的概念,但仍要遵循應(yīng)用的體系,Java 只能繼承一個(gè)類(lèi),但可以實(shí)現(xiàn)多個(gè)接口,所以你的某個(gè)類(lèi)型需要用 extends 限定,且有多種類(lèi)型的時(shí)候,只能存在一個(gè)是類(lèi),并且類(lèi)寫(xiě)在第一位,接口列在后面,也就是:

(泛型方法的類(lèi)型限定)

<T extends SomeClass & interface1 & interface2 & interface3>

(泛型類(lèi)中類(lèi)型參數(shù)的限制)

public class Demo<T extends Comparable & Serializable> { 
  // T類(lèi)型就可以用Comparable聲明的方法和Seriablizable所擁有的特性了 
} 

通配符泛型

為了解決類(lèi)型被限制死了不能動(dòng)態(tài)根據(jù)實(shí)例來(lái)確定的缺點(diǎn),引入了“通配符泛型”,針對(duì)上面的例子,使用通配泛型格式為<? extends Collection>,“?”代表未知類(lèi)型,這個(gè)類(lèi)型是實(shí)現(xiàn)Collection接口。

注意:

如果只指定了<?>,而沒(méi)有extends,則默認(rèn)是允許Object及其下的任何Java類(lèi)了。也就是任意類(lèi)。

通配符泛型不單可以向下限制,如<? extends Collection>,還可以向上限制,如<? super Double>,表示類(lèi)型只能接受Double及其上層父類(lèi)類(lèi)型,如Number、Object類(lèi)型的實(shí)例。

泛型類(lèi)定義可以有多個(gè)泛型參數(shù),中間用逗號(hào)隔開(kāi),還可以定義泛型接口,泛型方法。這些都與泛型類(lèi)中泛型的使用規(guī)則類(lèi)似。

4、泛型方法

是否擁有泛型方法,與其所在的類(lèi)是否泛型沒(méi)有關(guān)系。要定義泛型方法,只需將泛型參數(shù)列表置于返回值前。如:

public class GenericMethod { 

  public <T> void print(T x) { 
    System.out.println(x.getClass().getName()); 
  } 

  public static void main(String[] args) { 
    GenericMethod method = new GenericMethod(); 
    method.print(" "); 
    method.print(10); 
    method.print('a'); 
    method.print(method); 
  } 
} 

需要注意的是,一個(gè)static方法,無(wú)法訪(fǎng)問(wèn)泛型類(lèi)的類(lèi)型參數(shù),所以,若要static方法需要使用泛型能力,必須使其成為泛型方法。

泛型的好處如:

開(kāi)始版本

public void write(Integer i, Integer[] ia);
public void write(Double d, Double[] da);

泛型版本

public <T> void write(T t, T[] ta);

簡(jiǎn)便了代碼

定義泛型

定義在類(lèi)后面

緊跟類(lèi)名后面

public class TestClassDefine<T, S extends T>{......}

定義泛型 T, S, 且S 繼承 T

定義在方法裝飾符后面

緊跟修飾符后面(public)

public <T, S extends T> T testGenericMethodDefine(T t, S s){......}

定義泛型 T, S, 且S 繼承 T

實(shí)例化泛型

實(shí)例化定義在類(lèi)上的泛型

第一聲明類(lèi)變量或者實(shí)例化時(shí)。例如

List<String> list;
list = new ArrayList<String>;

第二繼承類(lèi)或者實(shí)現(xiàn)接口時(shí)。例如

public class MyList<E> extends ArrayList<E> implements List<E> {...} 

實(shí)例化定義方法上的泛型

當(dāng)調(diào)用范型方法時(shí),編譯器自動(dòng)對(duì)類(lèi)型參數(shù)(泛型)進(jìn)行賦值,當(dāng)不能成功賦值時(shí)報(bào)編譯錯(cuò)誤。

通配符(?)

上面有泛型的定義和賦值;當(dāng)在賦值的時(shí)候,上面一節(jié)說(shuō)賦值的都是為具體類(lèi)型,當(dāng)賦值的類(lèi)型不確定的時(shí)候,我們用通配符(?)代替了:

List<?> unknownList;
List<? extends Number> unknownNumberList;
List<? super Integer> unknownBaseLineIntgerList;

以上這篇詳談Java泛型中T和問(wèn)號(hào)(通配符)的區(qū)別就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 操作Properties配置文件詳解

    Java 操作Properties配置文件詳解

    這篇文章主要介紹了Java 操作Properties配置文件詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 深入探索Java常量池

    深入探索Java常量池

    這篇文章主要介紹了深入探索Java常量池,涉及靜態(tài)常量池和運(yùn)行時(shí)常量池的介紹,常量池的好處,8種基本數(shù)據(jù)類(lèi)型的包裝類(lèi)和常量池等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • java實(shí)現(xiàn)文件上傳的詳細(xì)步驟

    java實(shí)現(xiàn)文件上傳的詳細(xì)步驟

    文件上傳是用戶(hù)將本地文件通過(guò)Web頁(yè)面提交到服務(wù)器的過(guò)程,涉及客戶(hù)端、服務(wù)器端、上傳表單等組件,在SpringBoot中,通過(guò)MultipartFile接口處理上傳文件,并將其保存在服務(wù)器,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • java 如何讀取properties文件

    java 如何讀取properties文件

    這篇文章主要介紹了java 如何讀取properties文件,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-11-11
  • 背包問(wèn)題-動(dòng)態(tài)規(guī)劃java實(shí)現(xiàn)的分析與代碼

    背包問(wèn)題-動(dòng)態(tài)規(guī)劃java實(shí)現(xiàn)的分析與代碼

    這篇文章主要給大家介紹了關(guān)于背包問(wèn)題動(dòng)態(tài)規(guī)劃java實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Spring CGLlB動(dòng)態(tài)代理實(shí)現(xiàn)過(guò)程解析

    Spring CGLlB動(dòng)態(tài)代理實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了Spring CGLlB動(dòng)態(tài)代理實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java框架解說(shuō)之BIO NIO AIO不同IO模型演進(jìn)之路

    Java框架解說(shuō)之BIO NIO AIO不同IO模型演進(jìn)之路

    網(wǎng)上很多IO資料,對(duì)新手來(lái)說(shuō),越看越暈。根據(jù)自己的理解,總結(jié)對(duì)比了一下BIO、NIO、AIO,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Java編寫(xiě)的實(shí)體返回VO工具

    Java編寫(xiě)的實(shí)體返回VO工具

    VO(value object)通常用于業(yè)務(wù)層之間的數(shù)據(jù)傳遞,VO的屬性是根據(jù)當(dāng)前業(yè)務(wù)的不同而不同的,也就是說(shuō),它的每一個(gè)屬性都一一對(duì)應(yīng)當(dāng)前業(yè)務(wù)邏輯所需要的數(shù)據(jù)的名稱(chēng)。本文將介紹如何將實(shí)體轉(zhuǎn)換為vo對(duì)象
    2021-05-05
  • Java API如何實(shí)現(xiàn)向Hive批量導(dǎo)入數(shù)據(jù)

    Java API如何實(shí)現(xiàn)向Hive批量導(dǎo)入數(shù)據(jù)

    這篇文章主要介紹了Java API如何實(shí)現(xiàn)向Hive批量導(dǎo)入數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解Kotlin的空指針處理

    詳解Kotlin的空指針處理

    這篇文章主要介紹了詳解Kotlin的空指針處理的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評(píng)論