本文小編為大家詳細(xì)介紹“Java開發(fā)反射機(jī)制實(shí)例代碼分析”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Java開發(fā)反射機(jī)制實(shí)例代碼分析”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
公司專注于為企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、商城建設(shè),小程序開發(fā),軟件按需求定制網(wǎng)站等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。憑借多年豐富的經(jīng)驗(yàn),我們會(huì)仔細(xì)了解各客戶的需求而做出多方面的分析、設(shè)計(jì)、整合,為客戶設(shè)計(jì)出具風(fēng)格及創(chuàng)意性的商業(yè)解決方案,創(chuàng)新互聯(lián)建站更提供一系列網(wǎng)站制作和網(wǎng)站推廣的服務(wù)。
存在這樣一個(gè)類:
package com.example.demo; import com.alibaba.fastjson.annotation.JSONField; public class User { private String name; @Value( value ="age_a") private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
1 - Class clazz = Class.forName("com.example.demo.User");
注意一點(diǎn),這里的forName("xxx")的類名需要全名,且為接口或類,否則加載不了。
2 - User user = new User();
Class clazz2 = user.getClass();
3 - Class clazz3 = User.class;
以上三種方式,都可以獲取到類User的Class對(duì)象,通過Class,即可以開始玩反射了。
Class clazz = User.class; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("屬性名:"+field.getName()); System.out.println("屬性的類型:"+field.getGenericType().getTypeName()); }
打印輸出User的屬性和屬性類型——
屬性名:name
屬性的類型:java.lang.String
屬性名:age
屬性的類型:java.lang.String
利用反射獲取到類的字段屬性后,是不是可以利用反射來創(chuàng)建一個(gè)對(duì)象呢?答案是肯定的。
例如,可以類似下面代碼,通過反射得到的字段屬性,進(jìn)而創(chuàng)建一個(gè)對(duì)象。
Map<String,Object> fileds = new HashMap<>(); fileds.put("name","張三"); fileds.put("age","10"); Object o = User.class.newInstance(); Field[] fields = o.getClass().getDeclaredFields(); for (Field field : fields) { //設(shè)置后可用反射訪問訪問私有變量 field.setAccessible(true); //通過反射給屬性賦值 field.set(o,fileds.get(field.getName())); } User user1 = (User) o; System.out.println(user1.toString());
什么場(chǎng)景下可能需要這樣做的呢?像一些內(nèi)部數(shù)據(jù)與外部數(shù)據(jù)字段的映射,就可以通過類似的字段反射方式,將源數(shù)據(jù)映射給目標(biāo)數(shù)據(jù),進(jìn)而得到可以插入數(shù)據(jù)庫(kù)的目標(biāo)對(duì)象。
注意一點(diǎn),我們?cè)谠O(shè)置User類時(shí),對(duì)其中一個(gè)字段加了注解:@Value( value ="age_a")。這是一種設(shè)置值的注解,既然是設(shè)置值,是否還可以在代碼運(yùn)行過程中,根據(jù)不同情況來動(dòng)態(tài)修改呢?
字段上的注解,其實(shí)都存放在一個(gè)memberValues屬性里,這是一個(gè)map,可以這樣來獲取——
Field[] fields = User.class.getDeclaredFields(); for (Field field : fields) { //設(shè)置后可用反射訪問訪問私有變量 if ("age".equals(field.getName() )){ field.setAccessible(true); //獲取 annotation 這個(gè)代理實(shí)例所持有的 InvocationHandler InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class)); // 獲取 InvocationHandler 的 memberValues 字段 Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues"); memberValues.setAccessible(true); Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler); System.out.println(values); } }
debug打斷點(diǎn),可以看到——
這個(gè)Map<String,Object>存儲(chǔ)的是該@注解里的所有屬性值,這里,@Value只有一個(gè)value屬性——
public @interface Value { String value(); }
若把它換成類似@JSONField(name="age_a"),把上邊的代碼稍微修改下,如:
Field[] fields = User.class.getDeclaredFields(); for (Field field : fields) { if ("age".equals(field.getName() )){ field.setAccessible(true); InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(JSONField.class)); ...... } }
@JSONField注解的內(nèi)部屬性有如下方式——
再運(yùn)行剛剛的代碼,可以看到,這里Map<String,Object>獲取存儲(chǔ)到的,便是這個(gè)注解里所有的屬性與對(duì)應(yīng)的屬性值。
到了這一步,回到先前上邊的問題,若要?jiǎng)討B(tài)改變這個(gè)注解的值,怎么處理呢?
其實(shí),很簡(jiǎn)單,只需要直接進(jìn)行值設(shè)置就可以了,例如——
InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class)); Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues"); memberValues.setAccessible(true); Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler); values.put("value","new_age"); memberValues.setAccessible(false);
只是,注意一點(diǎn)是,這里的key需要對(duì)應(yīng)上注解里是屬性值。
Object o=User.class.newInstance(); //通過反射獲取到User的setAge方法,后面的String.class表示這個(gè)setAge方法的參數(shù)類型,若有多個(gè),則按順序列出 //同時(shí),若為其他類型,如List,Long,則為L(zhǎng)ist.class,Long.class Method m = (Method) o.getClass().getMethod("setAge",String.class); m.invoke(o,"name"); User user = (User) o; System.out.println(user);
打印可見,age已為name,說明setAge調(diào)用成功了。
這類使用場(chǎng)景,在代理當(dāng)中出現(xiàn)比較多。
最后,通過反射實(shí)現(xiàn)一個(gè)Map轉(zhuǎn)成對(duì)象的封裝工具——
public Object MapToObject(Object object,Map<String, Object> map) throws IllegalAccessException { Class cla = object.getClass(); Field[] fields = cla.getDeclaredFields(); for(Field field:fields){ field.setAccessible(true); if("serialVersionUID".equals(field.getName()))continue; if(map.get(field.getName())!=null) { Object value=map.get(field.getName()); value=convertValType(value,field.getType()); field.set(object, value); } } return object; } private static Object convertValType(Object value, Class<?> fieldTypeClass) { Object o = null; if (Long.class.getName().equals(fieldTypeClass.getName()) || long.class.getName().equals(fieldTypeClass.getName())) { o = Long.parseLong(value.toString()); } else if (Integer.class.getName().equals(fieldTypeClass.getName()) || int.class.getName().equals(fieldTypeClass.getName())) { o = Integer.parseInt(value.toString()); } else if (Float.class.getName().equals(fieldTypeClass.getName()) || float.class.getName().equals(fieldTypeClass.getName())) { o = Float.parseFloat(value.toString()); } else if (Double.class.getName().equals(fieldTypeClass.getName()) || double.class.getName().equals(fieldTypeClass.getName())) { o = Double.parseDouble(value.toString()); } else { retVal = o; } return retVal; }
讀到這里,這篇“Java開發(fā)反射機(jī)制實(shí)例代碼分析”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享名稱:Java開發(fā)反射機(jī)制實(shí)例代碼分析
網(wǎng)頁(yè)URL:http://www.chinadenli.net/article38/ggigsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣、商城網(wǎng)站、網(wǎng)站導(dǎo)航、ChatGPT、微信小程序、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)