您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Java反射常見API的實(shí)例介紹”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java反射常見API的實(shí)例介紹”吧!
static void initUser(User user) throws IllegalAccessException { // 獲取User類中所有的屬性(getFields無法獲得private屬性) Field[] fields = User.class.getDeclaredFields(); // 遍歷所有屬性 for (Field field : fields) { // 如果屬性上有此注解,則進(jìn)行賦值操作 if (field.isAnnotationPresent(InitSex.class)) { InitSex init = field.getAnnotation(InitSex.class); field.setAccessible(true); // 設(shè)置屬性的性別值 field.set(user, init.sex().toString()); System.out.println("完成屬性值的修改,修改值為:" + init.sex().toString()); } } }
第一種方法:當(dāng)你知道類的全路徑名時(shí),可使用Class.forName靜態(tài)方法來獲得Class對(duì)象。上面的示例就是通過這種方法獲得:
Class clz = Class.forName("com.choupangxia.reflect.User");
第二種方法:通過“.class”獲得。前提條件是在編譯前就能夠拿到對(duì)應(yīng)的類。
Class clz = User.class;
第三種:使用類對(duì)象的getClass()方法。
User user = new User(); Class clz = user.getClass();
可以通過Class對(duì)象的newInstance()方法和通過Constructor 對(duì)象的newInstance()方法創(chuàng)建類的實(shí)例對(duì)象。
第一種:通過Class對(duì)象的newInstance()方法。
Class clz = User.class; User user = (User) clz.newInstance();
第二種:通過Constructor對(duì)象的newInstance()方法。
Class clz = Class.forName("com.xxx.reflect.User"); Constructor constructor = clz.getConstructor(); User user = (User) constructor.newInstance();
其中第二種方法創(chuàng)建類對(duì)象可以選擇特定構(gòu)造方法,而通過 Class對(duì)象則只能使用默認(rèn)的無參數(shù)構(gòu)造方法。
Class clz = User.class; Constructor constructor = clz.getConstructor(String.class); User user = (User) constructor.newInstance("公眾號(hào)");
通過Class對(duì)象的getFields()方法獲取非私有屬性。
Field[] fields = clz.getFields(); for(Field field : fields){ System.out.println(field.getName()); }
上述實(shí)例中的User對(duì)象屬性都是private,無法直接通過上述方法獲取,可將其中一個(gè)屬性改為public,即可獲取。
通過Class對(duì)象的getDeclaredFields()方法獲取所有屬性。
Field[] fields = clz.getDeclaredFields(); for(Field field : fields){ System.out.println(field.getName()); }
執(zhí)行打印結(jié)果:
username age
當(dāng)然針對(duì)屬性的其他值也是可以獲取的,針對(duì)私有屬性的修改需要先調(diào)用field.setAccessible(true)方法,然后再進(jìn)行賦值。關(guān)于具體應(yīng)用,回頭看我們最開始關(guān)于注解的實(shí)例中的使用。
獲取方法的示例如下:
Method[] methods = clz.getMethods(); for(Method method : methods){ System.out.println(method.getName()); }
打印結(jié)果:
setUsername setAge getUsername getAge wait wait wait equals toString hashCode getClass notify notifyAll
可以看到,不僅獲取到了當(dāng)前類的方法,還獲取到了該類父類Object類中定義的方法。
關(guān)于獲取構(gòu)造器的方法上面已經(jīng)講到了,就不再贅述。而上述的這些方法在Class中都有相應(yīng)的重載的方法,可根據(jù)具體情況進(jìn)行靈活使用。
最后,我們?cè)倏匆粋€(gè)通過反射創(chuàng)建數(shù)組的實(shí)例。
@Test public void createArray() throws ClassNotFoundException { Class<?> cls = Class.forName("java.lang.String"); Object array = Array.newInstance(cls,5); // 向數(shù)組添加內(nèi)容 Array.set(array,0,"Hello"); Array.set(array,1,"公眾號(hào)"); Array.set(array,2,"Java"); // 獲取數(shù)組中指定位置的內(nèi)容 System.out.println(Array.get(array,2)); }
public class User { static String country; private String name; public int age; private Result<String> result; public void say(String world){ System.out.println("我說:" + world); } private void writeNote(){ System.out.println("寫日記"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Result<String> getResult() { return result; } public void setResult(Result<String> result) { this.result = result; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class ReflectTest { public static void main(String[] args) throws Exception{ reflectDemo(); } public static void reflectDemo() throws Exception{ Class clazz = Class.forName("kite.lab.reflect.User"); Field[] declaredFields = clazz.getDeclaredFields(); for(Field declaredField:declaredFields){ System.out.println(declaredField.getName()); } Method[] methods = clazz.getDeclaredMethods(); for(Method method:methods){ System.out.println(method.getName()); } Object userInstance = clazz.newInstance(); Method sayMethod = clazz.getDeclaredMethod("say", String.class); sayMethod.invoke(userInstance,"你好"); Method writeNoteMethod = clazz.getDeclaredMethod("writeNote"); writeNoteMethod.setAccessible(true); writeNoteMethod.invoke(userInstance); } }
說起反射,大家可能都知道性能差。那反射的性能為什么差呢?
根本的原因就是因?yàn)榉瓷涫莿?dòng)態(tài)加載,所以 jit 對(duì)其所做的優(yōu)化極其有限。
jit - 即時(shí)編譯器,是 JVM 優(yōu)化性能的殺手級(jí)利器,它會(huì)對(duì)熱點(diǎn)代碼進(jìn)行一系列優(yōu)化,比如非常重要的優(yōu)化手段-方法內(nèi)聯(lián)。而反射的代碼則享受不到這種待遇。
反射中性能最差的部分在于獲取方法和屬性的部分,比如 getMethod() 方法,是因?yàn)楂@取這個(gè)方法需要遍歷所有的方法列表,包括父類。而如果不是反射的話,那這個(gè)方法地址都是提前確定的。
到此,相信大家對(duì)“Java反射常見API的實(shí)例介紹”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。