电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

詳解Java 中泛型的實現原理

瀏覽:22日期:2022-08-15 17:25:24

泛型是 Java 開發中常用的技術,了解泛型的幾種形式和實現泛型的基本原理,有助于寫出更優質的代碼。本文總結了 Java 泛型的三種形式以及泛型實現原理。

泛型

泛型的本質是對類型進行參數化,在代碼邏輯不關注具體的數據類型時使用。例如:實現一個通用的排序算法,此時關注的是算法本身,而非排序的對象的類型。

泛型方法

如下定義了一個泛型方法, 聲明了一個類型變量,它可以應用于參數,返回值,和方法內的代碼邏輯。

class GenericMethod{ public <T> T[] sort(T[] elements){ return elements; }}泛型類

與泛型方法類似,泛型類也需要聲明類型變量,只不過位置放在了類名后面,作用的范圍包括了當前中的成員變量類型,方法參數類型,方法返回類型,以及方法內的代碼中。

子類繼承泛型類時或者實例化泛型類的對象時,需要指定具體的參數類型或者聲明一個參數變量。如下,SubGenericClass 繼承了泛型類 GenericClass,其中類型變量 ID 的值為 Integer,同時子類聲明了另一個類型變量 E,并將E 填入了父類聲明的 T 中。

class GenericClass<ID, T>{ }class SubGenericClass<T> extends GenericClass<Integer, T>{ }泛型接口

泛型接口與泛型類類似,也需要在接口名后面聲明類型變量,作用于接口中的抽象方法返回類型和參數類型。子類在實現泛型接口時需要填入具體的數據類型或者填入子類聲明的類型變量。

interface GenericInterface<T> { T append(T seg);}泛型的基本原理

泛型本質是將數據類型參數化,它通過擦除的方式來實現。聲明了泛型的 .java 源代碼,在編譯生成 .class 文件之后,泛型相關的信息就消失了。可以認為,源代碼中泛型相關的信息,就是提供給編譯器用的。泛型信息對 Java 編譯器可以見,對 Java 虛擬機不可見。

Java 編譯器通過如下方式實現擦除:

用 Object 或者界定類型替代泛型,產生的字節碼中只包含了原始的類,接口和方法; 在恰當的位置插入強制轉換代碼來確保類型安全; 在繼承了泛型類或接口的類中插入橋接方法來保留多態性。

Java 官方文檔原文

Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.Insert type casts if necessary to preserve type safety.Generate bridge methods to preserve polymorphism in extended generic types.

下面通過具體代碼來說明 Java 中的類型擦除。

實驗原理:先用 javac 將 .java 文件編譯成 .class 文件,再使用反編譯工具 jad 將 .class 文件反編成回 Java 代碼,反編譯出來的 Java 代碼內容反映的即為 .class 文件中的信息。

如下源代碼,定義 User 類,實現了 Comparable 接口,類型參數填入 User,實現 compareTo 方法。

class User implements Comparable<User> { String name; public int compareTo(User other){ return this.name.compareTo(other.name); }}

JDK 中 Comparable 接口源碼內容如下:

package java.lang;public interface Comparable<T>{ int compareTo(T o);}

我們首先反編譯它的接口,Comparable 接口的字節碼文件,可以在 $JRE_HOME/lib/rt.jar 中找到,將它復制到某個目錄。使用 jad.exe(需要另外安裝)反編譯這個 Comparable.class 文件。

$ jad Comparable.class

反編譯出來的內容放在 Comparable.jad 文件中,文件內容如下:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.// Jad home page: http://www.kpdus.com/jad.html// Decompiler options: packimports(3)// Source File Name: Comparable.javapackage java.lang;// Referenced classes of package java.lang:// Objectpublic interface Comparable{ public abstract int compareTo(Object obj);}

對比源代碼 Comparable.java 和反編譯代碼 Comparable.jad 的內容不難發現,反編譯之后的內容中已經沒有了類型變量 T 。compareTo 方法中的參數類型 T 也被替換成了 Object。這就符合上面提到的第 1 條擦除原則。這里演示的是用 Object 替換類型參數,使用界定類型替換類型參數的例子可以反編譯一下 Collections.class 試試,里面使用了大量的泛型。

使用 javac.exe 將 User.java 編譯成 .class 文件,然后使用 jad 將 .class 文件反編譯成 Java 代碼。

$ javac User.java$ jad User.class

User.jad 文件內容如下:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.// Jad home page: http://www.kpdus.com/jad.html// Decompiler options: packimports(3)// Source File Name: User.javaclass User implements Comparable{ User() { } public int compareTo(User user) { return name.compareTo(user.name); } // 橋接方法 public volatile int compareTo(Object obj) { return compareTo((User)obj); } String name;}

對比編輯的源代碼 User.java 和反編譯出來的代碼 User.jad,容易發現:類型參數沒有了,多了一個無參構造方法,多了一個 compareTo(Object obj) 方法,這個就是橋接方法,還可以發現參數 obj 被強轉成 User 再傳入 compareTo(User user) 方法。通過這些內容可以看到擦除規則 2 和規則 3 的實現方式。

強轉規則比較好理解,因為泛型被替換成了 Object,要調用具體類型的方法或者成員變量,當然需要先強轉成具體類型才能使用。那么插入的橋接方法該如何理解呢?

如果我們只按照下面方式去使用 User 類,這樣確實不需要參數類型為 Object 的橋接方法。

User user = new User();User other = new User();user.comparetTo(other);

但是,Java 中的多態特性允許我們使用一個父類或者接口的引用指向一個子類對象。

Comparable<User> user = new User();

而按照 Object 替換泛型參數原則,Comparable 接口中只有 compareTo(Object) 方法,假設沒有橋接方法,顯然如下代碼是不能運行的。所以 Java 編譯器需要為子類(泛型類的子類或泛型接口的實現類)中使用了泛型的方法額外生成一個橋接方法,通過這個方法來保證 Java 中的多態特性。

Comparable<User> user = new User();Object other = new User();user.compareTo(other);

而普通類中的泛型方法在進行類型擦除時不會產生橋接方法。例如:

class Dog{ <T> void eat(T[] food){ }}

類型擦除之后變成了:

class Dog{ Dog() { } void eat(Object aobj[]) { }}小結

Java 中的泛型有 3 種形式,泛型方法,泛型類,泛型接口。Java 通過在編譯時類型擦除的方式來實現泛型。擦除時使用 Object 或者界定類型替代泛型,同時在要調用具體類型方法或者成員變量的時候插入強轉代碼,為了保證多態特性,Java 編譯器還會為泛型類的子類生成橋接方法。類型信息在編譯階段被擦除之后,程序在運行期間無法獲取類型參數所對應的具體類型。

參考

https://docs.oracle.com/javase/tutorial/java/generics/index.html

https://stackoverflow.com/questions/25040837/generics-bridge-method-on-polymorphism

以上就是詳解Java 中泛型的實現原理的詳細內容,更多關于Java 泛型實現原理的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 高博医疗集团上海阿特蒙医院 | 橡胶粉碎机_橡胶磨粉机_轮胎粉碎机_轮胎磨粉机-河南鼎聚重工机械制造有限公司 | 膜结构车棚|上海膜结构车棚|上海车棚厂家|上海膜结构公司 | 管家婆-管家婆软件-管家婆辉煌-管家婆进销存-管家婆工贸ERP | 上海小程序开发-上海小程序制作公司-上海网站建设-公众号开发运营-软件外包公司-咏熠科技 | 保温杯,儿童婴童奶瓶,运动水壶「广告礼品杯定制厂家」超朗保温杯壶 | 深圳办公室装修-写字楼装修设计-深圳标榜装饰公司 | 多功能真空滤油机_润滑油全自动滤油机_高效真空滤油机价格-重庆润华通驰 | 四川成人高考_四川成考报名网 | 注塑模具_塑料模具_塑胶模具_范仕达【官网】_东莞模具设计与制造加工厂家 | 冷轧机|两肋冷轧机|扁钢冷轧机|倒立式拉丝机|钢筋拔丝机|收线机-巩义市华瑞重工机械制造有限公司 | 慈溪麦田广告公司,提供慈溪广告设计。| 旋转/数显粘度计-运动粘度测定仪-上海平轩科学仪器 | 洗砂机械-球磨制砂机-洗沙制砂机械设备_青州冠诚重工机械有限公司 | 游动电流仪-流通式浊度分析仪-杰普仪器(上海)有限公司 | 煤机配件厂家_刮板机配件_链轮轴组_河南双志机械设备有限公司 | 英语词典_成语词典_日语词典_法语词典_在线词典网 | 珠海白蚁防治_珠海灭鼠_珠海杀虫灭鼠_珠海灭蟑螂_珠海酒店消杀_珠海工厂杀虫灭鼠_立净虫控防治服务有限公司 | 地源热泵一体机,地源热泵厂家-淄博汇能环保设备有限公司 | CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 月嫂_保姆_育婴_催乳_母婴护理_产后康复_养老护理-吉祥到家家政 硫酸亚铁-聚合硫酸铁-除氟除磷剂-复合碳源-污水处理药剂厂家—长隆科技 | 河南15年专业网站建设制作设计,做网站就找郑州启凡网络公司 | 香港新时代国际美容美发化妆美甲培训学校-26年培训经验,值得信赖! | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | 电动手术床,医用护理床,led手术无影灯-曲阜明辉医疗设备有限公司 | 一体化污水处理设备_生活污水处理设备_全自动加药装置厂家-明基环保 | 乐泰胶水_loctite_乐泰胶_汉高乐泰授权(中国)总代理-鑫华良供应链 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 广东燎了网络科技有限公司官网-网站建设-珠海网络推广-高端营销型外贸网站建设-珠海专业h5建站公司「了了网」 | 上海道勤塑化有限公司 | 金刚网,金刚网窗纱,不锈钢网,金刚网厂家- 河北萨邦丝网制品有限公司 | 电气控制系统集成商-PLC控制柜变频控制柜-非标自动化定制-电气控制柜成套-NIDEC CT变频器-威肯自动化控制 | 东莞注册公司-代办营业执照-东莞公司注册代理记账-极刻财税 | 美国PARKER齿轮泵,美国PARKER柱塞泵,美国PARKER叶片泵,美国PARKER电磁阀,美国PARKER比例阀-上海维特锐实业发展有限公司二部 | 阳光1号桔柚_无核沃柑_柑橘新品种枝条苗木批发 - 苧金网 | 华禹护栏|锌钢护栏_阳台护栏_护栏厂家-华禹专注阳台护栏、楼梯栏杆、百叶窗、空调架、基坑护栏、道路护栏等锌钢护栏产品的生产销售。 | 产业规划_产业园区规划-产业投资选址及规划招商托管一体化服务商-中机院产业园区规划网 | 客服外包专业服务商_客服外包中心_网萌科技| 坏男孩影院-提供最新电影_动漫_综艺_电视剧_迅雷免费电影最新观看 | 中山市派格家具有限公司【官网】 | 卓能JOINTLEAN端子连接器厂家-专业提供PCB接线端子|轨道式端子|重载连接器|欧式连接器等电气连接产品和服务 |