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

Java泛型之上界下界通配符詳解

 更新時(shí)間:2019年06月19日 10:50:13   作者:JAVA專欄  
這篇文章主要介紹了Java泛型之上界下界通配符詳解,學(xué)習(xí)使用泛型編程時(shí),更令人困惑的一個(gè)方面是確定何時(shí)使用上限有界通配符以及何時(shí)使用下限有界通配符。本文提供一些設(shè)計(jì)代碼時(shí)要遵循的一些準(zhǔn)則。,需要的朋友可以參考下

泛型,繼承和子類

如你所知,只要類型兼容,就可以將一種類型的對(duì)象分配給另一種類型的對(duì)象。例如,你可以指定一個(gè)整數(shù)一個(gè)對(duì)象,因?yàn)閷?duì)象是一個(gè)整數(shù)的超類型:

Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger; // 好

在面向?qū)ο蟮男g(shù)語(yǔ)中,這被稱為“是一種”關(guān)系。由于Integer 是一種Object,因此允許賦值。但是Integer也是一種Number,所以下面的代碼也是有效的:

public void someMethod(Number n){/ * ... * /}
someMethod(new Integer(10)); // 好
someMethod(new Double(10.1)); // 好

泛型也是如此。您可以執(zhí)行泛型類型調(diào)用,將Number作為其類型參數(shù)傳遞,如果參數(shù)與Number兼容,則允許任何后續(xù)的add調(diào)用:

Box <Number> box = new Box <Number>();
box.add(new Integer(10)); // 好
box.add(new Double(10.1)); // 好

現(xiàn)在考慮以下方法:

public void boxTest(Box <Number> n){/ * ... * /}

它接受什么類型的論據(jù)?通過(guò)查看其簽名,您可以看到它接受一個(gè)類型為Box<Number>的參數(shù)。但是,這是什么意思?您是否可以按照您的預(yù)期傳遞Box<Integer>或Box<Double>?答案是“否”,因?yàn)锽ox<Integer>和Box<Double>不是Box<Number>的子類型。

這是在使用泛型編程時(shí)一個(gè)常見的誤解,也是一個(gè)需要學(xué)習(xí)的重要概念。

Box<Integer>不是Box<Number>的子類型,即使Integer是Number的子類型。

注意:給定兩個(gè)具體類型 A 和 B(例如,Number和Integer),MyClass<A> 與 MyClass<B>無(wú)關(guān),無(wú)論 A 和 B 是否相關(guān)。MyClass<A> 和 MyClass<B> 的公共父是Object。

有關(guān)如何在類型參數(shù)相關(guān)時(shí)在兩個(gè)泛型類之間創(chuàng)建類似子類型關(guān)系的信息,請(qǐng)參閱下面的通配符和子類型一節(jié)。

泛型類和子類型化

您可以通過(guò)擴(kuò)展(extends)泛型類或?qū)崿F(xiàn)(implements)泛型接口來(lái)對(duì)其進(jìn)行子類型化。一個(gè)類或接口的類型參數(shù)與另一個(gè)類或接口的類型參數(shù)之間的關(guān)系由extends和implements子句確定。

使用Collections類作為示例,ArrayList<E> 實(shí)現(xiàn) List<E>,List<E> 擴(kuò)展Collection<E>。所以 ArrayList<String>是List<String>的子類型,它是Collection<String>的子類型。只要不改變類型參數(shù),就會(huì)在類型之間保留子類型關(guān)系。

顯示Collection層次結(jié)構(gòu)示例的圖表:ArrayList<String>是 List<String>的子類型,二者都是Collection<String>的子類型。

現(xiàn)在假設(shè)我們想要定義我們自己的列表接口PayloadList,它將可選值泛型類型參數(shù)P的與每個(gè)元素相關(guān)聯(lián)。它的聲明可能如下:

interface PayloadList<E,P> extends List<E> {
void setPayload(int index, P val);
...
}

PayloadList的以下參數(shù)化是List<String>的子類型:

PayloadList<String,String>
PayloadList<String,Integer>
PayloadList<String,Exception>

PayLoadList層次結(jié)構(gòu)的示意圖:PayloadList<String,String>是List<String>的子類型,它是Collection<String>的子類型。 在PayloadList<String,String>的相同級(jí)別是PayloadList <String,Integer>和PayloadList<String,Exceptions>。

通配符和子類型

如 泛型,繼承和子類一節(jié)中所述,泛型類之間或接口之間幾乎并不因它們的類型參數(shù)而相關(guān)。但是,您可以使用通配符在泛型類或接口之間創(chuàng)建關(guān)系。

給定以下兩個(gè)常規(guī)(非泛型)類:

class A { /* ... */ }
class B extends A { /* ... */ }

編寫以下代碼是合理的:

B b = new B();
A a = b;

此示例顯示常規(guī)類的繼承遵循此子類型規(guī)則:如果B擴(kuò)展A,則類B是類A的子類型。此規(guī)則不適用于泛型類型:

List<B> lb = new ArrayList<>();
List<A> la = lb; //編譯時(shí)錯(cuò)誤

鑒于Integer是Number的子類型,List<Integer> 和 List<Number> 之間的關(guān)系是什么?

盡管Integer是Number的子類型,但List<Integer>不是List<Number>的子類型,實(shí)際上,這兩種類型不相關(guān)。List<Number>和 List<Integer> 的公共父是 List<?>。

上界(extends)的通配符與下界(super)通配符

為了在這些類之間創(chuàng)建關(guān)系以便代碼可以通過(guò) List<Integer> 的元素訪問(wèn)Number的方法,請(qǐng)使用上界的通配符:

List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK, List<?extends Integer>是 List< ? extends Number>的子類型

因?yàn)镮nteger是Number的子類型,而numList是Number對(duì)象的列表,所以intList(是一個(gè)Integer對(duì)象列表)和numList之間現(xiàn)在存在關(guān)系。下圖顯示了使用上限和下限通配符聲明的多個(gè) List 類之間的關(guān)系。

通配符使用指南

學(xué)習(xí)使用泛型編程時(shí),更令人困惑的一個(gè)方面是確定何時(shí)使用上限有界通配符以及何時(shí)使用下限有界通配符。本文提供一些設(shè)計(jì)代碼時(shí)要遵循的一些準(zhǔn)則。

為討論方便,認(rèn)為變量具備兩個(gè)功能:

一個(gè)“In”變量

“in”變量向代碼提供數(shù)據(jù)。想象一下帶有兩個(gè)參數(shù)的復(fù)制方法:copy(src,dest)。該SRC參數(shù)提供的數(shù)據(jù)被復(fù)制,因此它是“in”參數(shù)。

一個(gè)“Out”變量
“out”變量保存數(shù)據(jù)以供其他地方使用。在復(fù)制示例中,copy(src,dest),dest參數(shù)接受數(shù)據(jù),因此它是“out”參數(shù)。

當(dāng)然,一些變量既用于“in”又用于“out”目的 - 這種情況也在本文中也用到了。

在決定是否使用通配符以及適合使用哪種類型的通配符時(shí),可以使用“in”和“out”原則。以下列表提供了遵循的準(zhǔn)則:

通配符指南:

  • 使用extends關(guān)鍵字, 定義帶有上界通配符的“in”變量。
  • 使用super關(guān)鍵字,使用下界通配符定義“out”變量。
  • 在可以使用Object類中定義的方法訪問(wèn)“in”變量的情況下,使用無(wú)界通配符。
  • 在代碼需要作為“in”和“out”變量訪問(wèn)變量的情況下,不要使用通配符。

這些指南不適用于方法的返回類型。應(yīng)該避免使用通配符作為返回類型,因?yàn)樗鼜?qiáng)制程序員使用代碼來(lái)處理通配符。

List<? extends ...> 可以被非正式地認(rèn)為是只讀的,但這不是一個(gè)嚴(yán)格的保證。假設(shè)您有以下兩個(gè)類:

class NaturalNumber {
private int i;
public NaturalNumber(int i) { this.i = i; }
// ...
}
class EvenNumber extends NaturalNumber {
public EvenNumber(int i) { super(i); }
// ...
}

請(qǐng)考慮以下代碼:

List<EvenNumber> le = new ArrayList<>();
List<? extends NaturalNumber> ln = le;
ln.add(new NaturalNumber(35)); // compile-time error //編譯時(shí)錯(cuò)誤

因?yàn)長(zhǎng)ist<EvenNumber>是List<? extends NaturalNumber>,您可以賦值le給ln。但是你不能使用ln將自然數(shù)添加到偶數(shù)列表中。列表中的以下操作是可能的:

  • 您可以添加null。
  • 你可以調(diào)用清除。
  • 您可以獲取迭代器并調(diào)用remove。
  • 您可以捕獲通配符并寫入從列表中讀取的元素。

你可以看到List<? extends NaturalNumber>在嚴(yán)格意義上不是只讀的,但您可能會(huì)這樣想,因?yàn)槟鸁o(wú)法存儲(chǔ)新元素或更改列表中的現(xiàn)有元素。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java高并發(fā)InterruptedException異常引發(fā)思考

    java高并發(fā)InterruptedException異常引發(fā)思考

    這篇文章主要為大家介紹了java高并發(fā)InterruptedException異常引發(fā)思考,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • java實(shí)現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問(wèn)題示例

    java實(shí)現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問(wèn)題示例

    這篇文章主要介紹了java實(shí)現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問(wèn)題示例,需要的朋友可以參考下
    2014-05-05
  • Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 FTP軟件主界面(4)

    Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 FTP軟件主界面(4)

    這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件,F(xiàn)TP軟件主界面編寫的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • SWT(JFace) 圖片瀏覽器 實(shí)現(xiàn)代碼

    SWT(JFace) 圖片瀏覽器 實(shí)現(xiàn)代碼

    SWT(JFace)小制作:圖片瀏覽器
    2009-06-06
  • Java中類變量和類方法的基本使用

    Java中類變量和類方法的基本使用

    這篇文章主要介紹了Java中類變量和類方法的基本使用,類變量也叫靜態(tài)變量/靜態(tài)屬性,是該類的所有對(duì)象共享的變量,任何一個(gè)該類的對(duì)象訪問(wèn)它時(shí),取到的都是相同的值,同樣任何一個(gè)該類的對(duì)象去修改它時(shí),修改的也是同一個(gè)變量,需要的朋友可以參考下
    2023-07-07
  • Maven中resources標(biāo)簽的用法詳解

    Maven中resources標(biāo)簽的用法詳解

    本文主要介紹了Maven中resources標(biāo)簽的用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • java?-jar指定外部配置文件操作步驟

    java?-jar指定外部配置文件操作步驟

    這篇文章主要給大家介紹了關(guān)于java?-jar指定外部配置文件的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 詳解Spring如何解析占位符

    詳解Spring如何解析占位符

    Spring一直支持將屬性定義到外部的屬性的文件中,并使用占占位符的形式為使用"${}"包裝的屬性名稱,為了使用屬性占位符,我們必須配置一個(gè)PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer實(shí)例,本文將介紹如何解析占位符
    2021-06-06
  • java SSLContext創(chuàng)建方式

    java SSLContext創(chuàng)建方式

    這篇文章主要介紹了java SSLContext創(chuàng)建方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java多線程實(shí)現(xiàn)多人聊天室功能

    Java多線程實(shí)現(xiàn)多人聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Java多線程實(shí)現(xiàn)多人聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06

最新評(píng)論