詳解java 中泛型中的類型擦除和橋方法
在Java中,泛型的引入是為了在編譯時提供強類型檢查和支持泛型編程。為了實現(xiàn)泛型,Java編譯器應(yīng)用類型擦除實現(xiàn):
1、 用類型參數(shù)(type parameters)的限定(如果沒有就用Object)替換泛型類型中的所有類型參數(shù)。
2、 需要保持類型安全的時候加入類型轉(zhuǎn)換
3、 在extened 泛型類型中生成橋方法來保證多態(tài)性
類型擦除確保不會為已參數(shù)化了的類型(paramterized types)產(chǎn)生新類,這樣泛型能保證沒有運行時的負載。
泛型類型擦除
在類型擦除過程中,java編譯器擦除所有類型參數(shù),用它的限定或者Object(沒限定時)替換。
考慮下面的泛型類:
public class Node<T> { private T data; private Node<T> next; public Node(T data, Node<T> next) } this.data = data; this.next = next; } public T getData() { return data; } // ... }
因為類型參數(shù)T是非限定的,Java編譯器使用Object替換它:
public class Node { private Object data; private Node next; public Node(Object data, Node next) { this.data = data; this.next = next; } public Object getData() { return data; } // ... }
下面的例子,泛型Node類使用了限定類型參數(shù):
public class Node<T extends Comparable<T>> { private T data; private Node<T> next; public Node(T data, Node<T> next) { this.data = data; this.next = next; } public T getData() { return data; } // ...
編譯器會使用第一個限定類,Comparable替換限定參數(shù)類型T:
public class Node { private Comparable data; private Node next; public Node(Comparable data, Node next) { this.data = data; this.next = next; } public Comparable getData() { return data; } // ... }
同樣,泛型方法也可以擦除。規(guī)則類似,不細說。
類型擦除的影響和橋方法
有時候類型擦除會引起無法預(yù)知的情況。比如:
給定以下兩個類:
public class Node<T> { public T data; public Node(T data) { this.data = data; } public void setData(T data) { System.out.println("Node.setData"); this.data = data; } } public class MyNode extends Node<Integer> { public MyNode(Integer data) { super(data); } public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); } }
考慮以下代碼:
MyNode mn = new MyNode(5); Node n = mn; // 原生類型 – 編譯器會給出未檢查警告 n.setData("Hello"); Integer x = mn.data; // 會引發(fā)拋出ClassCastException
類型擦除后,代碼變成:
MyNode mn = new MyNode(5); Node n = (MyNode)mn; //原生類型 – 編譯器會給出未檢查警告 n.setData("Hello"); Integer x = (String)mn.data; //會引發(fā)拋出ClassCastException
public class Node { public Object data; public Node(Object data) { this.data = data; } public void setData(Object data) { System.out.println("Node.setData"); this.data = data; } } public class MyNode extends Node { public MyNode(Integer data) { super(data); } public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); } }
類型擦除后,方法的簽名已經(jīng)不匹配。Node 方法變成setData(Object),MyNode方法變成setData(Integer)。MyNode setData方法已經(jīng)不是覆蓋Node setData方法。
為了解決這個問題,維持泛型類型的多態(tài)性,java編譯器會生成一個橋方法:
class MyNode extends Node { // 編譯器生成的橋方法 // public void setData(Object data) { setData((Integer) data); } public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); } // ...
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
SpringBoot3使用?自定義注解+Jackson實現(xiàn)接口數(shù)據(jù)脫敏的步驟
本文介紹了一種以優(yōu)雅的方式實現(xiàn)對接口返回的敏感數(shù)據(jù),如手機號、郵箱、身份證等信息的脫敏處理,這種方法也是企業(yè)常用方法,話不多說我們一起來看一下吧2024-03-03Presto支持Elasticsearch數(shù)據(jù)源配置詳解
這篇文章主要為大家介紹了Presto支持Elasticsearch數(shù)據(jù)源配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12java 之JNA中的Memory和Pointer的使用方法
這篇文章主要介紹了java 之JNA中的Memory和Pointer的使用方法,文章基于Java的相關(guān)自來哦展開對Pointer和Memory的使用介紹,需要的小伙伴可以參考一下2022-04-04springboot結(jié)合mybatis-plus基于session模擬短信注冊功能
本文主要介紹了springboot結(jié)合mybatis-plus基于session模擬短信注冊功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11Intellij IDEA如何自定義注釋模板的實現(xiàn)方法
這篇文章主要介紹了Intellij IDEA如何自定義注釋模板的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05Spring JPA聯(lián)表查詢之OneToOne源碼詳解
這篇文章主要為大家介紹了Spring JPA聯(lián)表查詢之OneToOne源碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04