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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java泛型程序设计——翻译泛型表达式+翻译泛型方法

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java泛型程序设计——翻译泛型表达式+翻译泛型方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1) 本文描述+源代碼均 轉自 core java volume 1, 旨在理解 java泛型程序設計 的 翻譯泛型表達式+翻譯泛型方法 的知識;


【1】翻譯泛型表達式

1.1)當程序調用泛型方法時, 如果擦除了泛型返回類型, 編譯器插入類型轉換;

  • 1.1.1)看個荔枝:
Pair<Employee> buddies = ... Employee buddy = buddies.getFirst();
  • 擦除getFirst的返回類型后將返回Object類型。 編譯器自動插入 Employee 的強制類型轉換。
  • 也就是說, 編譯器吧這個方法調用翻譯為兩條虛擬機指令(Commands):
    • C1)對原始方法 Pair.getFirst 的調用;
    • C2)將返回的Object類型 強制轉換為 Employee 類型;

1.2)當存取一個泛型域時也要插入強制類型轉換。

  • 1.2.1)假設 Pair 類的first 域 和 second 域都是 公有的(這不是種好的編程風格, 但在java語法中,這是合法的)。
    表達式: Employee buddy = buddies.first; 也會在結果字節碼中插入強制類型轉換;

【2】翻譯泛型方法

2.1)類型擦除也會出現在泛型方法中。

public static <T extends Comparable> T min(T[] a):是一個完整的方法族;
  • 2.1.1)擦除類型后, 只剩下一個方法:
public static Comparable min(Comparable[] a)
  • 注意, 類型參數T 已經被擦除了, 只留下了限定類型 Comparable;

2.2)方法擦除帶來了兩個復雜問題。

  • 2.2.1)看個荔枝:
class DateInterval extends Pair<Date> {public void setSecond(Date second){if(second.compareTo(getFirst()) >= 0)super.setSecond(second);} }

對以上代碼的分析(Analysis):

  • A1)上述類的類型變量擦除后, 為
class DateInterval extends Pair // after erasure {public void setSecond(Date second){if(second.compareTo(getFirst()) >=0)super.setSecond(second);} }
  • A2)令人感到奇怪的是, 存在另一個從Pair 繼承的setSecond方法, 即
public void setSecond(Object second)

  • Attention)此時要注意, DateInterval內部應該是重寫了 Pair的 setSecond方法, 結果擦除類型參數后, 就不是重寫了, 破壞了類的多態性;

A3)它們顯然不是同一種方法, 因為有不同的類型參數, 一個是Object , 而另一個是 Date;(這里是干貨)
A4)然而不應該不一樣, 考慮下面的語句序列:

DateInterval interval = new DateInterval(); Pair<Date> pair = interval; // OK--assignment to superclass pair.setSecond(aDate); // "那這條語句調用哪個 setSecond方法呢? 是 setSecond(Object) 還是 setSecond(Date) 呢?"
  • A5)這里, 希望對setSecond 的調用 具有多態性, 并調用最合適的那個方法。 由于pair 引用DateInterval 對象,所以應該調用 DateInterval.setSecond;
  • A6)出現的問題:在于類型擦除與多態發生了沖突, 確實, 如上面的Attention所說, 變量類型擦除破壞了類的多態性;
  • A7)解決方法: 就需要編譯器在 DateInterval 類中生成一個橋方法(bridge method):
public void setSecond(Object second) //這里就調用了 重寫的 父類 DateInterval(Object) {setSecond((Date)second)}

2.3)上述引入了橋方法:要想了解他的工作過程, 跟蹤下列語句 pair.setSecond(aDate);

  • 2.3.1)變量pair 已經說明為類型 Pair , 并且這個類型只有一個簡單的方法叫做 setSecond, 即 setSecond(Object);
  • 2.3.2)虛擬機用 pair 引用的對象調用這個方法: 這個對象是 DateInterval 類型的, 因而將會調用 DateInterval.setSecond(Object) 方法;
  • 2.3.3)這個方法是合成的橋方法: 它調用 DateInterval.setSecond(Date)方法,在正是我們想要的;

2.4)橋方法也可以變得很奇怪, 如 DateInterval 方法覆蓋了 getSecond()方法:

class DateInterval extends Pair<ate> {public Date getSecond() {return (Date) super.getSecond().clone();} }

對以上代碼的分析(Analysis):

  • A1)在擦除的過程中, 有兩個getSecond方法:
    • A1.1) Date getSecond() // defined in DateInterval
    • A1.2) Object getSecond() // overrides the method defined in Pair to call the first method
  • A2)不能這樣編寫代碼(因為具有相同參數的兩個方法是不合法的, 他們都沒有參數)。
  • A3)但在虛擬機中, 用參數類型和返回類型確定一個方法, 因此, 編譯器可能產生兩個僅返回 類型不同的 方法字節碼, 虛擬機能夠正確處理這個情況;
    Annotation)

  • A1)橋方法不僅用于泛型類型; 還有, 在一個方法覆蓋另一個方法時可以指定一個更嚴格的返回類型:

public class Employee implements Clonealbe {public Employee clone() throws CloneNotSupportedException() {} }

對以上代碼的分析(Analysis):

  • A1) Object.clone 和 Employee.clone 方法被說成具有協變的返回類型;(具有協變的返回類型)
  • A2)實際上, Employee 類有兩個克隆方法(Methods):
    • M1) Employee clone();// defined above
    • M2) Object clone() ; // synthesized bridge method, overrides Object.clone;
  • A3)合成的橋方法調用了新定義的方法;

Conclusion)總之, 需要記住有關java泛型轉換的事實:

  • C1)虛擬機中沒有泛型, 只有普通的類和方法;
  • C2)所有的類型參數都是用它們的限定類型替換;
  • C3)橋方法被合成來保持多態;
  • C4)為保持類型安全性, 必要時插入強制類型轉換;

總結

以上是生活随笔為你收集整理的java泛型程序设计——翻译泛型表达式+翻译泛型方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。