日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java泛型简介–第6部分

發(fā)布時(shí)間:2023/12/3 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java泛型简介–第6部分 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是對(duì)泛型的介紹性討論的延續(xù), 此處的先前部分可以在此處找到。

在上一篇文章中,我們討論了關(guān)于類型參數(shù)的遞歸邊界。 我們看到了遞歸綁定如何幫助我們重用了車輛比較邏輯。 在該文章的結(jié)尾,我建議當(dāng)我們不夠小心時(shí),可能會(huì)發(fā)生類型混合。 今天我們將看到一個(gè)例子。

如果有人錯(cuò)誤地通過(guò)以下方式創(chuàng)建了Vehicle的子類,則可能會(huì)發(fā)生混合:

/*** Definition of Vehicle*/ public abstract class Vehicle<E extends Vehicle<E>> implements Comparable<E> {// other methods and propertiespublic int compareTo(E vehicle) {// method implementation} }/*** Definition of Bus*/ public class Bus extends Vehicle<Bus> {}/*** BiCycle, new subtype of Vehicle*/ public class BiCycle extends Vehicle<Bus> {}/*** Now this class’s compareTo method will take a Bus type* as its argument. As a result, you will not be able to compare* a BiCycle with another Bicycle, but with a Bus.*/ cycle.compareTo(anotherCycle); // This will generate a compile time error cycle.compareTo(bus); // but you will be able to do this without any error

枚舉不會(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í)例并初始化屬性。 如果我們可以在此處使用方法鏈接 ,那么我們可以編寫:

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類型,因?yàn)榫幾g器不知道這種轉(zhuǎn)換是否是可能的,即使它是因?yàn)榕1频亩x是由父<T>界。 同樣,由于我們將對(duì)象引用轉(zhuǎn)換為T ,因此編譯器將發(fā)出未經(jīng)檢查的警告。 為了抑制這種情況,我們?cè)谠O(shè)置器上方使用了@SuppressWarnings(“ unchecked”) 。

經(jīng)過(guò)上述修改,這樣做是完全有效的:

Child c = new Child().setAttrib1("Attribute 1").setAttrib6("Attribute 6");

當(dāng)以這種方式編寫方法設(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

總結(jié)

以上是生活随笔為你收集整理的Java泛型简介–第6部分的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。