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

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

Java泛型extends及super區別實例解析

瀏覽:36日期:2022-08-27 13:08:33

<? extends T>和<? super T>是Java泛型中的“通配符(Wildcards)”和“邊界(Bounds)”的概念。

<? extends T>:是指“上界通配符(Upper Bounds Wildcards)” <? super T>:是指“下界通配符(Lower Bounds Wildcards)”

為什么要用通配符和邊界?

使用泛型的過程中,經常出現一種很別扭的情況。比如按照題主的例子,我們有Fruit類,和它的派生類Apple類。

class Fruit {}class Apple extends Fruit {}

然后有一個最簡單的容器:Plate類。盤子里可以放一個泛型的“東西”。我們可以對這個東西做最簡單的“放”和“取”的動作:set( )和get( )方法。

class Plate<T>{ private T item; public Plate(T t){item=t;} public void set(T t){item=t;} public T get(){return item;}}

現在我定義一個“水果盤子”,邏輯上水果盤子當然可以裝蘋果:

Plate<Fruit> pfruit=new Plate<Apple>(new Apple());

但實際上Java編譯器不允許這個操作。會報錯,“裝蘋果的盤子”無法轉換成“裝水果的盤子”。

error: incompatible types: Plate<Apple> cannot be converted to Plate<Fruit>

所以問題就來了。實際上,編譯器腦袋里認定的邏輯是這樣的:

蘋果 IS-A 水果 裝蘋果的盤子 NOT-IS-A 裝水果的盤子

所以,就算容器里裝的東西之間有繼承關系,但容器之間是沒有繼承關系的。所以我們不可以把Plate的引用傳遞給Plate。

為了讓泛型用起來更舒服,Sun的大腦袋們就想出了<? extends T>和<? super T>的辦法,來讓”水果盤子“和”蘋果盤子“之間發生關系。

什么是上界?

下面代碼就是“上界通配符(Upper Bounds Wildcards)”:

Plate<? extends Fruit>

翻譯一下就是:一個能放水果以及一切是水果派生類的盤子。再直白點就是:啥水果都能放的盤子。這和我們人類的邏輯就比較接近了。Plate<? extends Fruit>和Plate<Apple>最大的區別就是:Plate<? extends Fruit>是Plate<Fruit>以及Plate<Apple>的基類。直接的好處就是,我們可以用“蘋果盤子”給“水果盤子”賦值了。

Plate<? extends Fruit> p=new Plate<Apple>(new Apple());

如果把Fruit和Apple的例子再擴展一下,食物分成水果和肉類,水果有蘋果和香蕉,肉類有豬肉和牛肉,蘋果還有兩種青蘋果和紅蘋果。

//Lev 1class Food{}//Lev 2class Fruit extends Food{}class Meat extends Food{}//Lev 3class Apple extends Fruit{}class Banana extends Fruit{}class Pork extends Meat{}class Beef extends Meat{}//Lev 4class RedApple extends Apple{}class GreenApple extends Apple{}

在這個體系中,下界通配符Plate<? extends Fruit>覆蓋下圖中藍色的區域。

Java泛型extends及super區別實例解析

什么是下界?

相對應的,“下界通配符(Lower Bounds Wildcards)”:

Plate<? super Fruit>

表達的就是相反的概念:一個能放水果以及一切是水果基類的盤子。Plate<? super Fruit>是Plate<Fruit>的基類,但不是Plate<Apple>的基類。對應剛才那個例子,Plate<? super Fruit>覆蓋下圖中紅色的區域。

Java泛型extends及super區別實例解析

上下界通配符的副作用

邊界讓Java不同泛型之間的轉換更容易了。但不要忘記,這樣的轉換也有一定的副作用。那就是容器的部分功能可能失效。

還是以剛才的Plate為例。我們可以對盤子做兩件事,往盤子里set()新東西,以及從盤子里get()東西。

class Plate<T>{ private T item; public Plate(T t){item=t;} public void set(T t){item=t;} public T get(){return item;}}

上界<? extends T>不能往里存,只能往外取

<? extends Fruit>會使往盤子里放東西的set( )方法失效。但取東西get( )方法還有效。比如下面例子里兩個set()方法,插入Apple和Fruit都報錯:

Plate<? extends Fruit> pfruit=new Plate<Apple>(new Apple()); //不能存入任何元素pfruit.set(new Fruit()); //Errorpfruit.set(new Apple()); //Error//讀取出來的東西只能存放在Fruit或它的基類里。Fruit newFruit1=pfruit.get();Object newFruit2=pfruit.get();Apple newFruit3=pfruit.get(); //Error

原因是編譯器只知道容器內是Fruit或者它的派生類,但具體是什么類型不知道。可能是Fruit?可能是Apple?也可能是Banana,RedApple,GreenApple?編譯器在看到后面用Plate賦值以后,盤子里沒有被標上有“蘋果”。而是標上一個占位符:CAP#1,來表示捕獲一個Fruit或Fruit的子類,具體是什么類不知道,代號CAP#1。然后無論是想往里插入Apple或者Meat或者Fruit編譯器都不知道能不能和這個CAP#1匹配,所以就都不允許。

所以通配符<?>和類型參數的區別就在于:

對編譯器來說所有的T都代表同一種類型。比如下面這個泛型方法里,三個T都指代同一個類型,要么都是String,要么都是Integer。

public <T> List<T> fill(T... t);

但通配符<?>沒有這種約束,Plate<?>單純的就表示:盤子里放了一個東西,是什么我不知道。

因此為了安全起見,Plate<? extends Fruit>里什么都放不進去。

下界<? super T>不影響往里存,但往外取只能放在Object對象里

使用下界<? super Fruit>會使從盤子里取東西的get( )方法部分失效,只能存放到Object對象里。set( )方法正常。

Plate<? super Fruit> pfruit=new Plate<Fruit>(new Fruit());//存入元素正常pfruit.set(new Fruit());pfruit.set(new Apple());//讀取出來的東西只能存放在Object類里。Apple newFruit3=pfruit.get(); //ErrorFruit newFruit1=pfruit.get(); //ErrorObject newFruit2=pfruit.get();

因為下界規定了元素的最小粒度的下限,實際上是放松了容器元素的類型控制。既然元素是Fruit的基類,那往里存粒度比Fruit小的都可以。但往外讀取元素就費勁了,只有所有類的基類Object對象才能裝下。但這樣的話,元素的類型信息就全部丟失。

PECS原則

最后看一下什么是PECS(Producer Extends Consumer Super)原則,已經很好理解了:

頻繁往外讀取內容的,適合用上界Extends。 經常往里插入的,適合用下界Super。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
主站蜘蛛池模板: 洁净实验室工程-成都手术室净化-无尘车间装修-四川华锐净化公司-洁净室专业厂家 | 罗茨真空机组,立式无油往复真空泵,2BV水环真空泵-力侨真空科技 | 防潮防水通风密闭门源头实力厂家 - 北京酷思帝克门窗 | 粉末冶金-粉末冶金齿轮-粉末冶金零件厂家-东莞市正朗精密金属零件有限公司 | 武汉高低温试验箱_恒温恒湿试验箱厂家-武汉蓝锐环境科技有限公司 | 交通信号灯生产厂家_红绿灯厂家_电子警察监控杆_标志杆厂家-沃霖电子科技 | 明渠式紫外线杀菌器-紫外线消毒器厂家-定州市优威环保 | loft装修,上海嘉定酒店式公寓装修公司—曼城装饰 | 电动不锈钢套筒阀-球面偏置气动钟阀-三通换向阀止回阀-永嘉鸿宇阀门有限公司 | 昆山新莱洁净应用材料股份有限公司-卫生级蝶阀,无菌取样阀,不锈钢隔膜阀,换向阀,离心泵 | 体感VRAR全息沉浸式3D投影多媒体展厅展会游戏互动-万展互动 | 电缆故障测试仪_电缆故障定位仪_探测仪_检测仪器_陕西意联电气厂家 | 流量检测仪-气密性检测装置-密封性试验仪-东莞市奥图自动化科技有限公司 | 耐酸碱胶管_耐腐蚀软管总成_化学品输送软管_漯河利通液压科技耐油耐磨喷砂软管|耐腐蚀化学软管 | 加盟店-品牌招商加盟-创业项目商机平台 | 变位机,焊接变位机,焊接变位器,小型变位机,小型焊接变位机-济南上弘机电设备有限公司 | 冷油器,取样冷却器,热力除氧器-连云港振辉机械设备有限公司 | B2B网站_B2B免费发布信息网站_B2B企业贸易平台 - 企资网 | 青岛代理记账_青岛李沧代理记账公司_青岛崂山代理记账一个月多少钱_青岛德辉财税事务所官网 | 东莞动力锂电池保护板_BMS智能软件保护板_锂电池主动均衡保护板-东莞市倡芯电子科技有限公司 | 网站建设-网站制作-网站设计-网站开发定制公司-网站SEO优化推广-咏熠软件 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 台湾Apex减速机_APEX行星减速机_台湾精锐减速机厂家代理【现货】-杭州摩森机电 | 净化车间装修_合肥厂房无尘室设计_合肥工厂洁净工程装修公司-安徽盛世和居装饰 | 水质传感器_水质监测站_雨量监测站_水文监测站-山东水境传感科技有限公司 | 列管冷凝器,刮板蒸发器,外盘管反应釜厂家-无锡曼旺化工设备有限公司 | 济南冷库安装-山东冷库设计|建造|冷库维修-山东齐雪制冷设备有限公司 | 西装定制/做厂家/公司_西装订做/制价格/费用-北京圣达信西装 | 化工ERP软件_化工新材料ERP系统_化工新材料MES软件_MES系统-广东顺景软件科技有限公司 | 自动记录数据电子台秤,记忆储存重量电子桌称,设定时间记录电子秤-昆山巨天 | 自动检重秤-动态称重机-重量分选秤-苏州金钻称重设备系统开发有限公司 | 纯水电导率测定仪-万用气体检测仪-低钠测定仪-米沃奇科技(北京)有限公司www.milwaukeeinst.cn 锂辉石检测仪器,水泥成分快速分析仪-湘潭宇科分析仪器有限公司 手术室净化装修-手术室净化工程公司-华锐手术室净化厂家 | 筒瓦厂家-仿古瓦-寺庙-古建琉璃瓦-宜兴市古典园林建筑陶瓷厂有限公司 | 双齿辊破碎机-大型狼牙破碎机视频-对辊破碎机价格/型号图片-金联机械设备生产厂家 | 选矿设备,选矿生产线,选矿工艺,选矿技术-昆明昆重矿山机械 | 艺术漆十大品牌_艺术涂料加盟代理_蒙太奇艺术涂料厂家品牌|艺术漆|微水泥|硅藻泥|乳胶漆 | 六维力传感器_六分量力传感器_模腔压力传感器-南京数智微传感科技有限公司 | 头条搜索极速版下载安装免费新版,头条搜索极速版邀请码怎么填写? - 欧远全 | 天津力值检测-天津管道检测-天津天诚工程检测技术有限公司 | 小型气象站_车载气象站_便携气象站-山东风途物联网 | 广州/东莞小字符喷码机-热转印打码机-喷码机厂家-广州瑞润科技 |