java 泛型嵌套泛型_Java泛型简介–第6部分
java 泛型嵌套泛型
這是關(guān)于泛型的介紹性討論的延續(xù), 此處的先前部分可以在此處找到。
在上一篇文章中,我們討論了關(guān)于類型參數(shù)的遞歸邊界。 我們看到了遞歸綁定如何幫助我們重用了車(chē)輛比較邏輯。 在該文章的結(jié)尾,我建議當(dāng)我們不夠謹(jǐn)慎時(shí),可能會(huì)發(fā)生類型混合。 今天我們將看到一個(gè)例子。
如果有人錯(cuò)誤地通過(guò)以下方式創(chuàng)建了Vehicle的子類,則可能會(huì)發(fā)生混合:
枚舉不會(huì)發(fā)生這種類型的混淆,因?yàn)镴VM負(fù)責(zé)子類化和為枚舉類型創(chuàng)建實(shí)例,但是如果我們?cè)诖a中使用這種樣式,則必須小心。
讓我們談?wù)勥f歸邊界的另一個(gè)有趣的應(yīng)用。 考慮以下類別:
public class MyClass {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public MyClass() {}public String getAttrib1() {return attrib1;}public void setAttrib1(String attrib1) {this.attrib1 = attrib1;}public String getAttrib2() {return attrib2;}public void setAttrib2(String attrib2) {this.attrib2 = attrib2;}public String getAttrib3() {return attrib3;}public void setAttrib3(String attrib3) {this.attrib3 = attrib3;}public String getAttrib4() {return attrib4;}public void setAttrib4(String attrib4) {this.attrib4 = attrib4;}public String getAttrib5() {return attrib5;}public void setAttrib5(String attrib5) {this.attrib5 = attrib5;} }如果我們要?jiǎng)?chuàng)建此類的實(shí)例,則可以執(zhí)行以下操作:
MyClass mc = new MyClass(); mc.setAttrib1("Attribute 1"); mc.setAttrib2("Attribute 2");上面的代碼創(chuàng)建該類的實(shí)例并初始化屬性。 如果我們可以在此處使用方法鏈接 ,那么我們可以編寫(xiě):
MyClass mc = new MyClass().setAttrib1("Attribute 1").setAttrib2("Attribute 2");顯然比第一個(gè)版本好得多。 但是,要啟用這種方法鏈接,我們需要通過(guò)以下方式修改MyClass :
public class MyClass {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public MyClass() {}public String getAttrib1() {return attrib1;}public MyClass setAttrib1(String attrib1) {this.attrib1 = attrib1;return this;}public String getAttrib2() {return attrib2;}public MyClass setAttrib2(String attrib2) {this.attrib2 = attrib2;return this;}public String getAttrib3() {return attrib3;}public MyClass setAttrib3(String attrib3) {this.attrib3 = attrib3;return this;}public String getAttrib4() {return attrib4;}public MyClass setAttrib4(String attrib4) {this.attrib4 = attrib4;return this;}public String getAttrib5() {return attrib5;}public MyClass setAttrib5(String attrib5) {this.attrib5 = attrib5;return this;} }然后我們將可以對(duì)此類的實(shí)例使用方法鏈接。 但是,如果我們想在涉及繼承的地方使用方法鏈接,那么事情就會(huì)變得混亂:
public abstract class Parent {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public Parent() {}public String getAttrib1() {return attrib1;}public Parent setAttrib1(String attrib1) {this.attrib1 = attrib1;return this;}public String getAttrib2() {return attrib2;}public Parent setAttrib2(String attrib2) {this.attrib2 = attrib2;return this;}public String getAttrib3() {return attrib3;}public Parent setAttrib3(String attrib3) {this.attrib3 = attrib3;return this;}public String getAttrib4() {return attrib4;}public Parent setAttrib4(String attrib4) {this.attrib4 = attrib4;return this;}public String getAttrib5() {return attrib5;}public Parent setAttrib5(String attrib5) {this.attrib5 = attrib5;return this;} }public class Child extends Parent {private String attrib6;private String attrib7;public Child() {}public String getAttrib6() {return attrib6;}public Child setAttrib6(String attrib6) {this.attrib6 = attrib6;return this;}public String getAttrib7() {return attrib7;}public Child setAttrib7(String attrib7) {this.attrib7 = attrib7;return this;} }/*** Now try using method chaining for instances of Child* in the following way, you will get compile time errors.*/ Child c = new Child().setAttrib1("Attribute 1").setAttrib6("Attribute 6");這樣做的原因是,即使Child從其父級(jí)繼承了所有的setter,所有這些setter方法的返回類型也都是Parent類型,而不是Child類型。 因此,第一個(gè)設(shè)置器將返回類型為Parent的引用,調(diào)用setAttrib6會(huì)導(dǎo)致編譯錯(cuò)誤,因?yàn)樗鼪](méi)有任何此類方法。
我們可以通過(guò)在Parent上引入通用類型參數(shù)并在其上定義遞歸綁定來(lái)解決此問(wèn)題。 它的所有子項(xiàng)從其擴(kuò)展時(shí)都將自己作為類型參數(shù)傳遞,從而確保setter方法將返回其類型的引用:
public abstract class Parent<T extends Parent<T>> {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public Parent() {}public String getAttrib1() {return attrib1;}@SuppressWarnings("unchecked")public T setAttrib1(String attrib1) {this.attrib1 = attrib1;return (T) this;}public String getAttrib2() {return attrib2;}@SuppressWarnings("unchecked")public T setAttrib2(String attrib2) {this.attrib2 = attrib2;return (T) this;}public String getAttrib3() {return attrib3;}@SuppressWarnings("unchecked")public T setAttrib3(String attrib3) {this.attrib3 = attrib3;return (T) this;}public String getAttrib4() {return attrib4;}@SuppressWarnings("unchecked")public T setAttrib4(String attrib4) {this.attrib4 = attrib4;return (T) this;}public String getAttrib5() {return attrib5;}@SuppressWarnings("unchecked")public T setAttrib5(String attrib5) {this.attrib5 = attrib5;return (T) this;} }public class Child extends Parent<Child> {private String attrib6;private String attrib7;public String getAttrib6() {return attrib6;}public Child setAttrib6(String attrib6) {this.attrib6 = attrib6;return this;}public String getAttrib7() {return attrib7;}public Child setAttrib7(String attrib7) {this.attrib7 = attrib7;return this;} }請(qǐng)注意,我們已經(jīng)明確地施放此為T(mén)類型,因?yàn)榫幾g器不知道這種轉(zhuǎn)換是否是可能的,即使它是因?yàn)榕1频亩x是由父<T>界。 同樣,由于我們將對(duì)象引用轉(zhuǎn)換為T(mén) ,因此編譯器將發(fā)出未經(jīng)檢查的警告。 為了抑制這種情況,我們?cè)谠O(shè)置器上方使用了@SuppressWarnings(“ unchecked”) 。
經(jīng)過(guò)上述修改,這樣做是完全有效的:
Child c = new Child().setAttrib1("Attribute 1").setAttrib6("Attribute 6");當(dāng)以這種方式編寫(xiě)方法設(shè)置器時(shí),我們應(yīng)注意不要將遞歸邊界用于其他任何目的,例如從父級(jí)訪問(wèn)子級(jí)狀態(tài),因?yàn)檫@會(huì)使父級(jí)暴露于其子類的內(nèi)部細(xì)節(jié),并最終破壞封裝。
通過(guò)這篇文章,我完成了泛型的基本介紹。 我在本系列中沒(méi)有討論太多的事情,因?yàn)槲艺J(rèn)為它們已經(jīng)超出了介紹的范圍。
直到下一次。
翻譯自: https://www.javacodegeeks.com/2014/07/an-introduction-to-generics-in-java-part-6.html
java 泛型嵌套泛型
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java 泛型嵌套泛型_Java泛型简介–第6部分的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 雷克沙新款 NQ790 SSD 上架:7
- 下一篇: 中国空间站第四次太空授课“天宫课堂”活动