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

您的位置:首頁技術(shù)文章
文章詳情頁

深入分析JAVA 反射和泛型

瀏覽:43日期:2022-08-30 16:33:28

從 JDK5 以后,Java 的 Class 類增加了泛型功能,從而允許使用泛型來限制 Class 類,例如,String.class 的類型實(shí)際上是 Class<String>。如果 Class 對(duì)應(yīng)的類暫時(shí)未知,則使用 Class<?>。通過在反射中使用泛型,可以避兔使用反射生成的對(duì)象需要強(qiáng)制類型轉(zhuǎn)換。

泛型和 Class 類

使用 Class<T> 泛型可以避免強(qiáng)制類型轉(zhuǎn)換。例如,下面提供一個(gè)簡單的對(duì)象工廠,該對(duì)象工廠可以根據(jù)指定類來提供該類的實(shí)例。

public class CrazyitObjectFactory { public static Object getInstance(String clsName) { try { // 創(chuàng)建指定類對(duì)應(yīng)的Class對(duì)象 Class cls = Class.forName(clsName); // 返回使用該Class對(duì)象所創(chuàng)建的實(shí)例 return cls.newInstance(); } catch (Exception e) { e.printStackTrace(); return null; } }}

上面程序中兩行粗體字代碼根據(jù)指定的字符串類型創(chuàng)建了一個(gè)新對(duì)象,但這個(gè)對(duì)象的類型是 Object,因此當(dāng)需要使用 CrazyitObjectFactory 的 getInstance() 方法來創(chuàng)建對(duì)象時(shí),將會(huì)看到如下代碼:

// 獲取實(shí)例后需要強(qiáng)制類型轉(zhuǎn)換Date d = (Date)Crazyit.getInstance('java.util.Date');

甚至出現(xiàn)如下代碼:

JFrame f = (JFrame)Crazyit.getInstance('java.util.Date');

上面代碼在編譯時(shí)不會(huì)有任何問題,但運(yùn)行時(shí)將拋出 ClassCastException 異常,因?yàn)槌绦蛟噲D將一個(gè) Date 對(duì)象轉(zhuǎn)換成 JFrame 對(duì)象。

如果將上面的 CrazyitObjectFactory 工廠類改寫成使用泛型后的 Class,就可以避免這種情況。

public class CrazyitObjectFactory2 { public static <T> T getInstance(Class<T> cls) { try { return cls.newInstance(); } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { // 獲取實(shí)例后無須類型轉(zhuǎn)換 Date d = CrazyitObjectFactory2.getInstance(Date.class); JFrame f = CrazyitObjectFactory2.getInstance(JFrame.class); }}

在上面程序的 getInstance() 方法中傳入一個(gè) Class<T> 參數(shù),這是一個(gè)泛型化的 Class 對(duì)象,調(diào)用該 Class 對(duì)象的 newInstance() 方法將返回一個(gè) T 對(duì)象,如程序中粗體字代碼所示。接下來當(dāng)使用 CrazyitObjectFactory2 工廠類的 getInstance() 方法來產(chǎn)生對(duì)象時(shí),無須使用強(qiáng)制類型轉(zhuǎn)換,系統(tǒng)會(huì)執(zhí)行更嚴(yán)格的檢查,不會(huì)出現(xiàn) ClassCastException 運(yùn)行時(shí)異常。

前面介紹使用 Array 類來創(chuàng)建數(shù)組時(shí),曾經(jīng)看到如下代碼:

// 使用 Array 的 newInstance 方法來創(chuàng)建一個(gè)數(shù)組Object arr = Array.newInstance(String.class, 10);

對(duì)于上面的代碼其實(shí)使用并不是非常方便,因?yàn)?newInstance() 方法返回的確實(shí)是一個(gè) String[] 數(shù)組,而不是簡單的 Object 對(duì)象。如果需要將對(duì)象當(dāng)成 String[] 數(shù)組使用,則必須使用強(qiáng)制類型轉(zhuǎn)換——這是不安全的操作。

為了示范泛型的優(yōu)勢,可以對(duì) Array 的 newInstance() 方法進(jìn)行包裝。

public class CrazyitArray { // 對(duì)Array的newInstance方法進(jìn)行包裝 @SuppressWarnings('unchecked') public static <T> T[] newInstance(Class<T> componentType, int length) { return (T[]) Array.newInstance(componentType, length); // ① } public static void main(String[] args) { // 使用CrazyitArray的newInstance()創(chuàng)建一維數(shù)組 String[] arr = CrazyitArray.newInstance(String.class, 10); // 使用CrazyitArray的newInstance()創(chuàng)建二維數(shù)組 // 在這種情況下,只要設(shè)置數(shù)組元素的類型是int[]即可。 int[][] intArr = CrazyitArray.newInstance(int[].class, 5); arr[5] = '瘋狂Java講義'; // intArr是二維數(shù)組,初始化該數(shù)組的第二個(gè)數(shù)組元素 // 二維數(shù)組的元素必須是一維數(shù)組 intArr[1] = new int[] { 23, 12 }; System.out.println(arr[5]); System.out.println(intArr[1][1]); }}

上面程序中粗體字代碼定義的 newInstance() 方法對(duì) Array 類提供的 newInstance() 方法進(jìn)行了包裝,將方法簽名改成了 public static <T> T[] newInstance(Class<T> componentType, int length),這就保證程序通過該 newInstance() 方法創(chuàng)建數(shù)組時(shí)的返回值就是數(shù)組對(duì)象,而不是 Object 對(duì)象,從而避免了強(qiáng)制類型轉(zhuǎn)換。

提示:程序在①行代碼處將會(huì)有一個(gè) unchecked 編譯警告,所以程序使用了 @SuppressWarnings 來抑制這個(gè)警告信息。

使用反射來獲取泛型信息

通過指定類對(duì)應(yīng)的 Class 對(duì)象,可以獲得該類里包含的所有成員變量,不管該成員變量是使用 private 修飾,還是使用 public 修飾。獲得了成員變量對(duì)應(yīng)的 Field 對(duì)象后,就可以很容易地獲得該成員變量的數(shù)據(jù)類型,即使用如下代碼即可獲得指定成員變量的類型。

// 獲取成員變量 f 的類型Class<?> a = f.getType();

但這種方式只對(duì)普通類型的成員變量有效。如果該成員變量的類型是有泛型類型的類型,如 Map<String, Integer> 類型,則不能誰確地得到該成員變量的泛型參數(shù)。

為了獲得指定成員變量的泛型類型,應(yīng)先使用如下方法來獲取該成員變量的泛型類型。

// 獲得成員變量 f 的泛型類型Type gType = f.getGenericType();

然后將 Type 對(duì)象強(qiáng)制類型轉(zhuǎn)換為 ParameterizedType 對(duì)象,ParameterizedType 代表被參數(shù)化的類型,也就是增加了泛型限制的類型。ParameterizedType 類提供了如下兩個(gè)方法。

getRawType():返回沒有泛型信息的原始類型。 getActualTypeArguments():返回泛型參數(shù)的類型。

下面是一個(gè)獲取泛型類型的完整程序。

public class GenericTest { private Map<String, Integer> score; public static void main(String[] args) throws Exception { Class<GenericTest> clazz = GenericTest.class; Field f = clazz.getDeclaredField('score'); // 直接使用getType()取出的類型只對(duì)普通類型的成員變量有效 Class<?> a = f.getType(); // 下面將看到僅輸出java.util.Map System.out.println('score的類型是:' + a); // 獲得成員變量f的泛型類型 Type gType = f.getGenericType(); // 如果gType類型是ParameterizedType對(duì)象 if (gType instanceof ParameterizedType) { // 強(qiáng)制類型轉(zhuǎn)換 ParameterizedType pType = (ParameterizedType) gType; // 獲取原始類型 Type rType = pType.getRawType(); System.out.println('原始類型是:' + rType); // 取得泛型類型的泛型參數(shù) Type[] tArgs = pType.getActualTypeArguments(); System.out.println('泛型信息是:'); for (int i = 0; i < tArgs.length; i++) {System.out.println('第' + i + '個(gè)泛型類型是:' + tArgs[i]); } } else { System.out.println('獲取泛型類型出錯(cuò)!'); } }}

上面程序中的粗體字代碼就是取得泛型類型的關(guān)鍵代碼。運(yùn)行上面程序,將看到如下運(yùn)行結(jié)果:

score的類型是:interface java.util.Map原始類型是:interface java.util.Map泛型信息是:第0個(gè)泛型類型是:class java.lang.String第1個(gè)泛型類型是:class java.lang.Integer

從上面的運(yùn)行結(jié)果可以看出,使用 getType() 方法只能獲取普通類型的成員變量的數(shù)據(jù)類型:對(duì)于增加了泛型的成員變量,應(yīng)該使用 getGenericType() 方法來取得其類型。

提示:Type 也是 java.lang.reflect 包下的一個(gè)接口,該接口代表所有類型的公共高級(jí)接口,Class 是 Type 接口的實(shí)現(xiàn)類。Type 包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型等。

以上就是深入分析JAVA 反射和泛型的詳細(xì)內(nèi)容,更多關(guān)于JAVA 反射和泛型的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 心得体会网_心得体会格式范文模板 | 除湿机|工业除湿机|抽湿器|大型地下室车间仓库吊顶防爆除湿机|抽湿烘干房|新风除湿机|调温/降温除湿机|恒温恒湿机|加湿机-杭州川田电器有限公司 | 合肥角钢_合肥槽钢_安徽镀锌管厂家-昆瑟商贸有限公司 | 北京工业设计公司-产品外观设计-产品设计公司-千策良品工业设计 北京翻译公司-专业合同翻译-医学标书翻译收费标准-慕迪灵 | 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | 水环真空泵厂家,2bv真空泵,2be真空泵-淄博真空设备厂 | 湖州织里童装_女童男童中大童装_款式多尺码全_织里儿童网【官网】-嘉兴嘉乐网络科技有限公司 | 电缆接头-防爆电缆接头-格兰头-金属电缆接头-防爆填料函 | crm客户关系管理系统,销售管理系统,crm系统,在线crm,移动crm系统 - 爱客crm | 自清洗过滤器_全自动过滤器_全自动反冲洗过滤器_量子过滤器-滑漮滴 | 自动检重秤-动态称重机-重量分选秤-苏州金钻称重设备系统开发有限公司 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 沥青车辙成型机-车托式混凝土取芯机-混凝土塑料试模|鑫高仪器 | 钢木实验台-全钢实验台-化验室通风柜-实验室装修厂家-杭州博扬实验设备 | 苏州西朗门业-欧盟CE|莱茵UL双认证的快速卷帘门品牌厂家 | 真空泵维修保养,普发,阿尔卡特,荏原,卡西亚玛,莱宝,爱德华干式螺杆真空泵维修-东莞比其尔真空机电设备有限公司 | 新能源汽车电池软连接,铜铝复合膜柔性连接,电力母排-容发智能科技(无锡)有限公司 | 东莞猎头公司_深圳猎头公司_广州猎头公司-广东万诚猎头提供企业中高端人才招聘服务 | 婚博会2024时间表_婚博会门票领取_婚博会地址-婚博会官网 | 层流手术室净化装修-检验科ICU改造施工-华锐净化工程-特殊科室建设厂家 | 干洗店加盟_洗衣店加盟_干洗店设备-伊蔻干洗「武汉总部」 | 顺辉瓷砖-大国品牌-中国顺辉| J.S.Bach 圣巴赫_高端背景音乐系统_官网 | 氧化锆陶瓷_氧化锆陶瓷加工_氧化锆陶瓷生产厂家-康柏工业陶瓷有限公司 | 冷热冲击试验箱_温度冲击试验箱价格_冷热冲击箱排名_林频厂家 | 网站制作优化_网站SEO推广解决方案-无锡首宸信息科技公司 | 自进式锚杆-自钻式中空注浆锚杆-洛阳恒诺锚固锚杆生产厂家 | 股指期货-期货开户-交易手续费佣金加1分-保证金低-期货公司排名靠前-万利信息开户 | 垃圾压缩设备_垃圾处理设备_智能移动式垃圾压缩设备--山东明莱环保设备有限公司 | 陕西视频监控,智能安防监控,安防系统-西安鑫安5A安防工程公司 | 众能联合-提供高空车_升降机_吊车_挖机等一站工程设备租赁 | 电渗析,废酸回收,双极膜-山东天维膜技术有限公司 | 气动隔膜泵厂家-温州永嘉定远泵阀有限公司 | 标策网-专注公司商业知识服务、助力企业发展 | 伟秀电气有限公司-10kv高低压开关柜-高低压配电柜-中置柜-充气柜-欧式箱变-高压真空断路器厂家 | 新疆系统集成_新疆系统集成公司_系统集成项目-新疆利成科技 | 成都软件开发_OA|ERP|CRM|管理系统定制开发_成都码邻蜀科技 | 科昊仪器超纯水机系统-可成气相液氮罐-美菱超低温冰箱-西安昊兴生物科技有限公司 | 玄米影院| 电动高压冲洗车_价格-江苏速利达机车有限公司 | MTK核心板|MTK开发板|MTK模块|4G核心板|4G模块|5G核心板|5G模块|安卓核心板|安卓模块|高通核心板-深圳市新移科技有限公司 |