日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

一文搞懂Java中的反射機制

瀏覽:208日期:2022-08-26 17:15:59

前一段時間一直忙,所以沒什么時間寫博客,拖了這么久,也該更新更新了。最近看到各種知識付費的推出,感覺是好事,也是壞事,好事是對知識沉淀的認可與推動,壞事是感覺很多人忙于把自己的知識變現(xiàn),相對的在沉淀上做的實際還不夠,我對此暫時還沒有什么想法,總覺得,慢慢來,會更快一點,自己掌握好節(jié)奏就好。

好了,言歸正傳。

反射機制是Java中的一個很強大的特性,可以在運行時獲取類的信息,比如說類的父類,接口,全部方法名及參數(shù),全部常量和變量,可以說類在反射面前已經(jīng)衣不遮體了(咳咳,這是正規(guī)車)。先舉一個小栗子,大家隨意感受一下:

public void testA(){ String name = 'java.lang.String'; try{ Class cl = Class.forName(name); Class supercl = cl.getSuperclass(); String modifiers = Modifier.toString(cl.getModifiers()); if (modifiers.length() > 0){System.out.print(modifiers + ' '); } System.out.print(name); if (supercl != null && supercl != Object.class){System.out.print(' extents ' + supercl.getName()); } System.out.print('{n'); printFields(cl); System.out.println(); printConstructors(cl); System.out.println(); printMethods(cl); System.out.println('}'); }catch (ClassNotFoundException e){ e.printStackTrace(); } System.exit(0); }

private static void printConstructors(Class cl){ Constructor[] constructors = cl.getDeclaredConstructors();for (Constructor c : constructors){ String name = c.getName(); System.out.print(' '); String modifiers = Modifier.toString(c.getModifiers()); if (modifiers.length() > 0){System.out.print(modifiers + ' '); } System.out.print(name + '('); Class[] paraTypes = c.getParameterTypes(); for (int j = 0; j < paraTypes.length; j++){if (j > 0){ System.out.print(', ');}System.out.print(paraTypes[j].getSimpleName()); } System.out.println(');'); } } private static void printMethods(Class cl){ Method[] methods = cl.getDeclaredMethods(); for (Method m : methods){ Class retType = m.getReturnType(); String name = m.getName(); System.out.print(' '); String modifiers = Modifier.toString(m.getModifiers()); if (modifiers.length() > 0){System.out.print(modifiers + ' '); } System.out.print(retType.getSimpleName() + ' ' + name +'('); Class[] paramTypes = m.getParameterTypes(); for(int j = 0; j < paramTypes.length; j++){if (j > 0){ System.out.print(', ');}System.out.print(paramTypes[j].getName()); } System.out.println(');'); } } private static void printFields(Class cl){ Field[] fields = cl.getFields(); for (Field f : fields){ Class type = f.getType(); String name = f.getName(); System.out.print(' '); String modifiers = Modifier.toString(f.getModifiers()); if (modifiers.length() > 0){System.out.print(modifiers + ' '); } System.out.println(type.getSimpleName() + ' ' + name +';'); } }

調(diào)用testA方法輸出如下:

public final java.lang.String{ public static final Comparator CASE_INSENSITIVE_ORDER; public java.lang.String(byte[], int, int); public java.lang.String(byte[], Charset); public java.lang.String(byte[], String); public java.lang.String(byte[], int, int, Charset); public java.lang.String(byte[], int, int, String); java.lang.String(char[], boolean); public java.lang.String(StringBuilder); public java.lang.String(StringBuffer); public java.lang.String(byte[]); public java.lang.String(int[], int, int); public java.lang.String(); public java.lang.String(char[]); public java.lang.String(String); public java.lang.String(char[], int, int); public java.lang.String(byte[], int); public java.lang.String(byte[], int, int, int); public boolean equals(java.lang.Object); public String toString(); public int hashCode(); public int compareTo(java.lang.String); public volatile int compareTo(java.lang.Object); public int indexOf(java.lang.String, int); public int indexOf(java.lang.String); public int indexOf(int, int); public int indexOf(int); static int indexOf([C, int, int, [C, int, int, int); static int indexOf([C, int, int, java.lang.String, int); public static String valueOf(int); public static String valueOf(long); public static String valueOf(float); public static String valueOf(boolean); public static String valueOf([C); public static String valueOf([C, int, int); public static String valueOf(java.lang.Object); public static String valueOf(char); public static String valueOf(double); public char charAt(int); private static void checkBounds([B, int, int); public int codePointAt(int); public int codePointBefore(int); public int codePointCount(int, int); public int compareToIgnoreCase(java.lang.String); public String concat(java.lang.String); public boolean contains(java.lang.CharSequence); public boolean contentEquals(java.lang.CharSequence); public boolean contentEquals(java.lang.StringBuffer); public static String copyValueOf([C); public static String copyValueOf([C, int, int); public boolean endsWith(java.lang.String); public boolean equalsIgnoreCase(java.lang.String); public static transient String format(java.util.Locale, java.lang.String, [Ljava.lang.Object;); public static transient String format(java.lang.String, [Ljava.lang.Object;); public void getBytes(int, int, [B, int); public byte[] getBytes(java.nio.charset.Charset); public byte[] getBytes(java.lang.String); public byte[] getBytes(); public void getChars(int, int, [C, int); void getChars([C, int); private int indexOfSupplementary(int, int); public native String intern(); public boolean isEmpty(); public static transient String join(java.lang.CharSequence, [Ljava.lang.CharSequence;); public static String join(java.lang.CharSequence, java.lang.Iterable); public int lastIndexOf(int); public int lastIndexOf(java.lang.String); static int lastIndexOf([C, int, int, java.lang.String, int); public int lastIndexOf(java.lang.String, int); public int lastIndexOf(int, int); static int lastIndexOf([C, int, int, [C, int, int, int); private int lastIndexOfSupplementary(int, int); public int length(); public boolean matches(java.lang.String); private boolean nonSyncContentEquals(java.lang.AbstractStringBuilder); public int offsetByCodePoints(int, int); public boolean regionMatches(int, java.lang.String, int, int); public boolean regionMatches(boolean, int, java.lang.String, int, int); public String replace(char, char); public String replace(java.lang.CharSequence, java.lang.CharSequence); public String replaceAll(java.lang.String, java.lang.String); public String replaceFirst(java.lang.String, java.lang.String); public String[] split(java.lang.String); public String[] split(java.lang.String, int); public boolean startsWith(java.lang.String, int); public boolean startsWith(java.lang.String); public CharSequence subSequence(int, int); public String substring(int); public String substring(int, int); public char[] toCharArray(); public String toLowerCase(java.util.Locale); public String toLowerCase(); public String toUpperCase(); public String toUpperCase(java.util.Locale); public String trim();}

這里把String類型的所有方法和變量都獲取到了,使用的僅僅是String類型的全名。當然,反射的功能不僅僅是獲取類的信息,還可以在運行時動態(tài)創(chuàng)建對象,回想一下,我們正常的對象使用,都是需要在代碼中先聲明,然后才能使用它,但是使用反射后,就能在運行期間動態(tài)創(chuàng)建對象并調(diào)用其中的方法,甚至還能直接查看類的私有成員變量,還能獲取類的注解信息,在泛型中類型判斷時也經(jīng)常會用到。反射可以說完全打破了類的封裝性,把類的信息全部暴露了出來。

上面的代碼看不太明白也沒關系,只要稍微感受一下反射的能力就好了。介紹完了反射能做的事情,本篇教程就不再寫一些玩具代碼了,這次以一個實用型的代碼為媒介來介紹反射。

在開發(fā)中,經(jīng)常會遇到兩個不同類對象之間的復制,把一個類中的字段信息get取出來,然后set到另一個類中,大部分情況下,兩個類對應的字段是一樣,每次這樣使用是很麻煩的,那么利用反射就可以實現(xiàn)一個封裝,只需要調(diào)用一個方法即可實現(xiàn)簡單的類字段復制。

那么,先來想想,要復制一個類對象的所有字段信息到另一個類對象中,首先,怎么獲取一個類的某個字段的值呢?我們先來編寫一個方法:

/** * 獲取對象的指定字段的值 * @param obj 目標對象 * @param fieldName 目標字段 * @return 返回字段值 * @throws Exception 可能拋出異常 */ private static Object getFieldValue(Object obj, String fieldName) throws Exception{ //獲取類型信息 Class clazz = obj.getClass(); //取對應的字段信息 Field field = clazz.getDeclaredField(fieldName); //設置可訪問權(quán)限 field.setAccessible(true); //取字段值 Object value = field.get(obj); return value; }

這里使用了兩個之前沒有說過的類,一個是Class,是不是很眼熟,想一想,我們每次定義一個類的時候是不是都要用到它,哈哈,那你就想錯了,那是class關鍵詞,java是大小寫的敏感的,這里的Class是一個類名,那這個類是干嘛用的呢?

虛擬機在加載每一個類的時候,會自動生成一個對應的Class類來保存該類的信息,可以理解為Class類是那個類的代理類,是連接實際類與類加載器的橋梁,可以通過它來獲取虛擬機的類加載器引用,從而實現(xiàn)更多的騷操作。Class類是一個泛型類,每個類都有對應的一個Class類,比如String對應的Class類就是Class<String>。

Class有很多方法來獲取更多關于類的信息,這里使用getDeclaredField方法來獲取指定字段信息,返回的是Field類型對象,這個對象里存儲著關于字段的一些信息,如字段名稱,字段類型,字段修飾符,字段可訪問性等,setAccessible方法可以設置字段的可訪問性質(zhì),這樣就能直接訪問private修飾的字段了,然后使用get方法來獲取指定對象的對應字段的值。

我們來測試一下:

public void testB(){ try{ Employee employee = new Employee(); employee.setName('Frank'); employee.setSalary(6666.66); System.out.println((String)getFieldValue(employee,'name')); System.out.println((double)getFieldValue(employee,'salary')); }catch (Exception e){ e.printStackTrace(); } }

輸出如下:

Frank6666.66

接下來,我們需要獲取類中所有字段,然后在另一個類中查找是否有對應字段,如果有的話就設置字段的值到相應的字段中。

/** * 復制一個類對象屬性到另一個類對象中 * @param objA 需要復制的對象 * @param objB 復制到的目標對象類型 * @return 返回復制后的目標對象 */ private static void parseObj(Object objA,Object objB) throws Exception{ if (objA == null){ return; } //獲取objA的類信息 Class classA = objA.getClass(); Class classB = objB.getClass(); try { //獲取objA的所有字段 Field[] fieldsA = classA.getDeclaredFields(); //獲取objB的所有字段 Field[] fieldsB = classB.getDeclaredFields(); if (fieldsA == null || fieldsA.length <= 0 || fieldsB == null || fieldsB.length <= 0){return; } //生成查詢map Map<String,Field> fieldMap = new HashMap<>(); for (Field field:fieldsA){fieldMap.put(field.getName(),field); } //開始復制字段信息 for (Field fieldB : fieldsB){//查找是否在objB的字段中存在該字段Field fielaA = fieldMap.get(fieldB.getName());if (fielaA != null){ fieldB.setAccessible(true); fieldB.set(objB,getFieldValue(objA,fielaA.getName()));} } } catch (IllegalStateException e) { throw new IllegalStateException('instace fail: ' ,e); } }

這里獲取到classA和classB的所有字段之后,先生成了一個map用于查找,可以減少遍歷次數(shù),然后之后只需要遍歷一次就可以判斷相應字段是否存在,如果存在則取出對應值設置到相應的字段里去。

接下來測試一下:

public void testB(){ try{ //生成Employee對象 Employee employee = new Employee('Frank',6666.66); //生成一個Manager對象 Manager manager = new Manager(); //復制對象 parseObj(employee,manager); System.out.println(manager.getName()); System.out.println(manager.getSalary()); }catch (Exception e){ e.printStackTrace(); } }

public class Employee { private String name; private Double salary; public Employee(String name, Double salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; }}

public class Manager { private String name; private Double salary; private Double bonus; public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public Double getBonus() { return bonus; } public void setBonus(Double bonus) { this.bonus = bonus; }}

輸出如下:

Frank6666.66

完美,這樣我們就利用了反射機制完美的把相同的字段在不同類的對象之間進行了復制,這里僅僅是兩個字段,所以可能好處不明顯,但事實上,實際開發(fā)中,經(jīng)常會有將BO轉(zhuǎn)換為VO的操作,這時候,這個操作就很有必要了,簡單的一行命令就可以代替一大堆的get和set操作。

當然,使用反射機制固然高端大氣上檔次,但是也是一把雙刃劍,使用不當很可能會帶來嚴重后果,而且使用反射的話,會占用更多資源,運行效率也會降低,上述工具類是用運行效率換開發(fā)效率。開發(fā)中不建議大量使用,還是那句話,技術只是手段,需要使用的時候再使用,不要為了使用而使用。

至于反射中的其他方法和姿勢,大家盡可以慢慢去摸索,這里僅僅是拋磚引玉。

至此,本篇講解完畢,歡迎大家繼續(xù)關注。

以上就是一文搞懂Java中的反射機制的詳細內(nèi)容,更多關于Java反射機制的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
一区二区国产在线| 午夜久久av | 99视频精品| 婷婷中文字幕一区| 尤物在线精品| 亚洲欧美日韩国产| 喷白浆一区二区| 中文字幕一区二区三区日韩精品 | av综合电影网站| 久久精品三级| 91欧美日韩| 久久精品高清| 噜噜噜躁狠狠躁狠狠精品视频 | 喷白浆一区二区| 日韩中出av| 日韩亚洲国产欧美| 视频一区二区三区入口| 青青草91视频| 麻豆极品一区二区三区| 国产高潮在线| 欧美日韩国产在线一区| 亚洲精品九九| 麻豆精品久久久| 日韩一区二区三区在线免费观看| 香蕉成人久久| 亚洲专区视频| 日韩免费av| 日韩国产在线观看| 久久婷婷一区| 国产精品一页| 伊人久久亚洲影院| 韩国一区二区三区视频| 蜜臀精品久久久久久蜜臀| 成人综合一区| 91欧美极品| 国产日产一区| 日韩av网站在线免费观看| 精品一区二区三区四区五区| 久久精品91| 亚洲欧洲国产精品一区| 久久中文欧美| 黄色亚洲免费| 国产高清精品二区| 国产综合视频| 日本精品国产| 欧美日韩尤物久久| 免费黄网站欧美| 精品美女视频 | 成人在线视频中文字幕| 亚洲一区欧美二区| 欧美黑人做爰爽爽爽| 精品一区在线| 国产欧美日韩一区二区三区四区 | 欧美在线亚洲| 国产精久久久| 六月婷婷一区| av中文资源在线资源免费观看| 午夜在线观看免费一区| 精品国产成人| 亚洲在线观看| 精品国产美女a久久9999| 欧美综合国产| 伊人精品在线| 日韩在线电影| 鲁大师影院一区二区三区| 日韩一区欧美| 国产中文欧美日韩在线| 国产精品主播| 男女男精品视频网| 国产麻豆综合| 激情综合亚洲| 日韩精品2区| 国产一区二区三区不卡视频网站 | 美女精品一区二区| 午夜在线精品偷拍| 日韩免费在线| 国产日产精品_国产精品毛片| 九一精品国产| 成人午夜在线| 欧美久久香蕉| 免播放器亚洲| 亚洲www啪成人一区二区| 国产精品v日韩精品v欧美精品网站| 亚洲综合精品| 欧美+亚洲+精品+三区| 韩国女主播一区二区三区| 日韩av网站在线观看| 1024精品久久久久久久久| 超级白嫩亚洲国产第一| 美女国产精品久久久| 日韩高清不卡在线| 午夜在线视频一区二区区别| 久久久久国产| 久久精品五月| 欧美色综合网| 四虎精品一区二区免费| 尤物精品在线| 欧美成人日韩| 久久九九精品| 亚洲女同av| 成人在线视频区| 免费高潮视频95在线观看网站| 精品国产91| 日韩伦理一区| 亚洲欧美一区在线| 视频一区视频二区中文字幕| 亚洲日本在线观看视频| 欧美日一区二区三区在线观看国产免| 国产欧美日韩精品高清二区综合区 | 国产精品最新自拍| 日本va欧美va精品发布| 亚洲三区欧美一区国产二区| 丝袜诱惑制服诱惑色一区在线观看| 亚洲午夜视频| 久久蜜桃精品| 久久伦理在线| 激情综合激情| 欧美+亚洲+精品+三区| 国产综合精品| 国产视频一区免费看| 夜夜精品视频| 亚洲综合电影一区二区三区| 亚洲一区激情| 亚洲区欧美区| 综合激情五月婷婷| 日韩高清二区| 国产精品欧美大片| 牛牛精品成人免费视频| 国产一区丝袜| 美女网站视频一区| 99久久九九| 黄色日韩在线| 美女被久久久| 日韩有吗在线观看| 国产日韩欧美三区| 风间由美中文字幕在线看视频国产欧美| 精品三级在线观看视频| 国产va在线视频| 少妇久久久久| 亚洲婷婷在线| 蜜桃一区二区三区在线| 加勒比视频一区| 欧美男人天堂| 亚洲免费一区三区| 久久久久久一区二区| 麻豆精品91| 国产一区福利| 亚洲一区二区三区高清不卡| 国产精东传媒成人av电影| av亚洲在线观看| 国产香蕉精品| 国内精品福利| 国产精品99久久久久久董美香| 欧美va亚洲va日韩∨a综合色| 亚洲+小说+欧美+激情+另类| 日韩av自拍| 深夜日韩欧美| 欧美一区自拍| 亚洲深夜视频| 日韩中文字幕麻豆| 97精品资源在线观看| 国产精品国产一区| 先锋影音国产一区| 欧美国产亚洲精品| 欧美日韩精品一区二区视频| 亚洲影院天堂中文av色| 精品国产黄a∨片高清在线| 午夜国产一区二区| 国产亚洲观看| 日本免费一区二区三区四区| 老司机久久99久久精品播放免费| 久久超碰99| 欧美1区2区3区| 欧美日韩xxxx| 99免费精品| 亚洲精品护士| 日韩大片在线播放| 日韩精品高清不卡| 蜜臀国产一区| 日韩精品一区二区三区中文| 国产精品13p| 亚洲一级淫片| 日韩欧美网址| 日本一区二区中文字幕| 精品国产a一区二区三区v免费| 午夜国产精品视频免费体验区| 国产九九精品| 亚洲综合三区| 国产成人黄色| 亚洲1区在线| 99精品国产一区二区三区| 青青草伊人久久| 欧美日韩一区二区三区视频播放| 国产精品一区二区三区四区在线观看| 免播放器亚洲| 新版的欧美在线视频| 九九久久国产| 国产经典一区| 国产精品一区二区三区美女 | 久久国产精品免费精品3p|