中的占位符如何配合extends關(guān)鍵字使用,形如。泛型定義存在于這三種形式中:泛型類、泛型接口、泛型方法。 一般的泛型定義中的..."/>
您好,登錄后才能下訂單哦!
本文主要介紹在泛型定義中的< >中的占位符如何配合extends關(guān)鍵字使用,形如<T extends Integer>。泛型定義存在于這三種形式中:泛型類、泛型接口、泛型方法。
接下來本文將以幾個(gè)示例和具體分析來講解剩下的知識(shí)點(diǎn)。
類型參數(shù)多邊界的分析
此例中的泛型類,類型參數(shù)帶有多個(gè)邊界。講下類的實(shí)際意義:Dimension代表物體的方位、HasColor代表物體的顏色、Weight代表物體的重量。
interface HasColor { java.awt.Color getColor(); } class Colored<T extends HasColor> { T item; Colored(T item) { this.item = item; } T getItem() { return item; } // The bound allows you to call a method: java.awt.Color color() { return item.getColor(); } } class Dimension { public int x, y, z; } // This won't work -- class must be first, then interfaces: // class ColoredDimension<T extends HasColor & Dimension> { } // Multiple bounds: class ColoredDimension<T extends Dimension & HasColor> { T item; ColoredDimension(T item) { this.item = item; } T getItem() { return item; } java.awt.Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } interface Weight { int weight(); } // As with inheritance, you can have only one // concrete class but multiple interfaces: class Solid<T extends Dimension & HasColor & Weight> { T item; Solid(T item) { this.item = item; } T getItem() { return item; } java.awt.Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } int weight() { return item.weight(); } } class Bounded extends Dimension implements HasColor, Weight { public java.awt.Color getColor() { return null; } public int weight() { return 0; } } public class BasicBounds { public static void main(String[] args) { Solid<Bounded> solid = new Solid<Bounded>(new Bounded()); solid.color(); solid.getY(); solid.weight(); } } ///:~
class derivedBounded extends Bounded {} class Bounded1 extends Dimension implements HasColor, Weight { public java.awt.Color getColor() { return null; } public int weight() { return 0; } } public class BasicBounds { public static void main(String[] args) { //Solid<Bounded> solid = new Solid<Integer>(new derivedBounded());//給定的具體類型不符合邊界 Solid<Bounded> solid1 = new Solid<Bounded>(new derivedBounded());//可以傳遞具體類型Bounded的子類 //Solid<Bounded> solid2 = new Solid<Bounded>(new Bounded1());//編譯報(bào)錯(cuò),因?yàn)榉盒偷撵o態(tài)類型檢查 solid1.color(); solid1.getY(); solid1.weight(); } } ///:~
根據(jù)上一條,那么new Solid<Integer>(new Bounded())這里指定的具體類型,由于和泛型類定義的T類型參數(shù)的要求extends Dimension & HasColor & Weight不相符,所以編譯會(huì)報(bào)錯(cuò);給構(gòu)造器傳值時(shí),實(shí)參可以是Bounded的子類;一個(gè)同樣繼承了相同邊界的類Bounded1 ,不能傳遞給構(gòu)造器,因?yàn)轭愋鸵呀?jīng)被指定為Bounded了。
但是類型參數(shù)有多個(gè)邊界時(shí),java內(nèi)部即java字節(jié)碼到底是怎么處理的呢:
public static void main(java.lang.String[]); Code: 0: new #2 // class Solid 3: dup 4: new #3 // class Bounded 7: dup 8: invokespecial #4 // Method Bounded."<init>":()V 11: invokespecial #5 // Method Solid."<init>":(LDimension;)V 14: astore_1
從Method Solid."<init>":(LDimension;)V可以看到,給Solid的構(gòu)造器傳遞參數(shù)時(shí),編譯器認(rèn)為這個(gè)形參是個(gè)Dimension,這就是編譯器處理多個(gè)邊界的方法,永遠(yuǎn)處理為第一個(gè)邊界,即類型擦除為第一個(gè)邊界。但剩下的兩個(gè)邊界怎么辦呢,這里都被處理第一個(gè)邊界了,我們?cè)偃タ匆幌耂olid.class的反編譯代碼就能找到答案:
// Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) import java.awt.Color; class Solid<T extends Dimension & HasColor & Weight> { T item; Solid(T item) { this.item = item; } T getItem() { return this.item; } Color color() { return ((HasColor)this.item).getColor();//類型轉(zhuǎn)換為其他邊界,再調(diào)用方法 } int getX() { return this.item.x; } int getY() { return this.item.y; } int getZ() { return this.item.z; } int weight() { return ((Weight)this.item).weight();//類型轉(zhuǎn)換為其他邊界,再調(diào)用方法 } }
當(dāng)調(diào)用的方法不屬于第一個(gè)邊界時(shí),就進(jìn)行類型轉(zhuǎn)換處理為其他邊界就行,反正T肯定是符合extends Dimension & HasColor & Weight的。
繼承有邊界要求的泛型類
通過觀察上例可知,Colored、ColoredDimension、Solid這三個(gè)類在持有對(duì)象的方面有冗余的地方:都有同一個(gè)成員變量、同一個(gè)構(gòu)造器、同一個(gè)get函數(shù)。而類型參數(shù)上,邊界也是依次疊加的。同樣,對(duì)于這些邊界所帶來的屬性和方法,也是冗余的。
所以下例對(duì)其進(jìn)行了修改,通過繼承來消除冗余,注意,下面繼承的泛型類對(duì)類型參數(shù)是有邊界要求的:
//HoldItem對(duì)邊界T沒有要求 class HoldItem<T> { T item; HoldItem(T item) { this.item = item; } T getItem() { return item; } } //Colored2對(duì)邊界T有HasColor的要求 class Colored2<T extends HasColor> extends HoldItem<T> { Colored2(T item) { super(item); } java.awt.Color color() { return item.getColor(); } } //ColoredDimension2對(duì)邊界T有Dimension & HasColor的要求 class ColoredDimension2<T extends Dimension & HasColor> extends Colored2<T> { ColoredDimension2(T item) { super(item); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } //Solid2對(duì)邊界T有Dimension & HasColor & Weight的要求,不過沒有類繼承它了 class Solid2<T extends Dimension & HasColor & Weight> extends ColoredDimension2<T> { Solid2(T item) { super(item); } int weight() { return item.weight(); } } public class InheritBounds { public static void main(String[] args) { Solid2<Bounded> solid2 = new Solid2<Bounded>(new Bounded()); solid2.color(); solid2.getY(); solid2.weight(); } } ///:~
總結(jié)一下:
當(dāng)一個(gè)泛型類繼承另一個(gè)泛型類時(shí)(前者屬于“定義泛型類”,后者屬于“使用泛型類”),且使用了同一個(gè)類型參數(shù)時(shí),定義泛型類的類型參數(shù)邊界定義一定要小于等于使用的那個(gè)泛型類的邊界要求。
泛型方法中的邊界定義
泛型方法中對(duì)類型參數(shù)的邊界定義,同樣也得符合使用的泛型類的邊界要求。此例中,泛型類同樣繼承別的泛型類,分析同上不贅述。講下類的實(shí)際意義:一系列接口代表了超能力、一系列類代表了超級(jí)英雄,它們擁有一個(gè)超能力的成員變量。
import java.util.*; interface SuperPower {} interface XRayVision extends SuperPower { void seeThroughWalls(); } interface SuperHearing extends SuperPower { void hearSubtleNoises(); } interface SuperSmell extends SuperPower { void trackBySmell(); } class SuperHero<POWER extends SuperPower> { POWER power; SuperHero(POWER power) { this.power = power; } POWER getPower() { return power; } } class SuperSleuth<POWER extends XRayVision> extends SuperHero<POWER> { SuperSleuth(POWER power) { super(power); } void see() { power.seeThroughWalls(); } } class CanineHero<POWER extends SuperHearing & SuperSmell> extends SuperHero<POWER> { CanineHero(POWER power) { super(power); } void hear() { power.hearSubtleNoises(); } void smell() { power.trackBySmell(); } } class SuperHearSmell implements SuperHearing, SuperSmell { public void hearSubtleNoises() {} public void trackBySmell() {} } class DogBoy extends CanineHero<SuperHearSmell> { DogBoy() { super(new SuperHearSmell()); } } public class EpicBattle { // Bounds in generic methods: static <POWER extends SuperHearing> void useSuperHearing(SuperHero<POWER> hero) {//泛型方法 hero.getPower().hearSubtleNoises(); } static <POWER extends SuperHearing & SuperSmell> void superFind(SuperHero<POWER> hero) {//泛型方法 hero.getPower().hearSubtleNoises(); hero.getPower().trackBySmell(); } public static void main(String[] args) { DogBoy dogBoy = new DogBoy(); useSuperHearing(dogBoy); superFind(dogBoy); // You can do this: List<? extends SuperHearing> audioBoys; // But you can't do this: // List<? extends SuperHearing & SuperSmell> dogBoys; } } ///:~
其他
本文例子均來自java編程思想,例子本身不錯(cuò),但奈何作者對(duì)其做的講解很少,所以本人為其加上了詳細(xì)的分析。其實(shí)這些例子都需要反復(fù)琢磨,精讀之后才會(huì)對(duì)泛型的extends關(guān)鍵字有深刻的理解。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。