這篇文章主要介紹“java反射機(jī)制怎么實(shí)現(xiàn)”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“java反射機(jī)制怎么實(shí)現(xiàn)”文章能幫助大家解決問(wèn)題。
為斗門等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及斗門網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站制作、成都網(wǎng)站建設(shè)、斗門網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
1.獲取Class對(duì)象的三種方式
1. 通過(guò)對(duì)象的getClass()方法 Class c1=(new User()).getClass(); 2. 通過(guò)字節(jié)碼文件獲取 Class c2=User.class; 3. 通過(guò)Class類的靜態(tài)方法獲取 Class c3=Class.forName("com.bee.entity.User");
同一個(gè)類只會(huì)被加載一次
public class Test { public static void main(String[] args) { String path = "demo6.TestBean"; try { Class> clazz1 = Class.forName(path); System.out.println(clazz1.hashCode()); Class> class2 = Class.forName(path); System.out.println(class2.hashCode()); } catch (Exception e) { e.printStackTrace(); } } }
輸出
366712642 366712642
Class對(duì)象專門用來(lái)存放類的信息。一個(gè)類只對(duì)應(yīng)一個(gè)Class對(duì)象。因?yàn)?,類的?duì)象雖然可以有多個(gè),但對(duì)應(yīng)的類只有一個(gè)。
利用反射獲取類的信息
先定義一個(gè)類TestBean
public class TestBean { private String name; private int age; public TestBean() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public TestBean(String name, int age) { super(); this.name = name; this.age = age; } }
讀取上述類TestBean的信息
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { String path = "demo.TestBean"; try { Class> clazz = Class.forName(path); // 獲取類的名字 System.out.println(clazz.getName()); // 獲得包全路徑名 System.out.println(clazz.getSimpleName()); // 只獲得類名 // 獲取屬性信息 Field[] fields1 = clazz.getFields(); // 只能獲取public屬性 Field[] fields2 = clazz.getDeclaredFields(); // 可以獲得private屬性(可以獲得所有的屬性) Field field3 = clazz.getDeclaredField("name"); for (Field field : fields2) { System.out.println("屬性:" + field); } // 獲取方法信息 // clazz.getMethod(name, parameterTypes) 只能獲得public方法 Method[] methods = clazz.getDeclaredMethods(); Method method1 = clazz.getDeclaredMethod("getName", null); // 如果方法有參數(shù),必須傳遞參數(shù)類型對(duì)應(yīng)的Class對(duì)象。 Method method2 = clazz.getDeclaredMethod("setName", String.class); for (Method method : methods) { System.out.println("方法:" + method); } // 獲得構(gòu)造器信息 // Constructor[] constructors=clazz.getConstructors() 只能獲得public構(gòu)造方法 Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println("構(gòu)造器:" + constructor); } // 獲取無(wú)參構(gòu)造器 Constructor cons1 = clazz.getDeclaredConstructor(null); System.out.println("無(wú)參構(gòu)造器:" + cons1); // 獲取有參構(gòu)造器 Constructor cons2 = clazz.getDeclaredConstructor(String.class, int.class); System.out.println("有參構(gòu)造器:" + cons2); } catch (Exception e) { e.printStackTrace(); } } }
通過(guò)反射動(dòng)態(tài)操作構(gòu)造器,方法,屬性
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { String path = "demo.TestBean"; try { Classclazz = (Class ) Class.forName(path); // 通過(guò)反射構(gòu)造對(duì)象 TestBean tb = clazz.newInstance(); // 調(diào)用TestBean的無(wú)參構(gòu)造方法 // 對(duì)于JavaBean/POJO/DTO必須要配置一個(gè)無(wú)參構(gòu)造器,以便框架使用newInstance()構(gòu)建對(duì)象實(shí)例。 System.out.println(tb); // 調(diào)用有參構(gòu)造器 Constructor cons1 = clazz.getDeclaredConstructor(String.class, int.class); TestBean tb1 = cons1.newInstance("黃忠", 83); System.out.println(tb1.getName() + tb1.getAge() + "歲"); // 通過(guò)反射調(diào)用普通方法 TestBean tb2 = clazz.newInstance(); tb2.setName("云長(zhǎng)"); // 等效于下邊的invoke()方法 tb2.setAge(57); // 等效于下邊的invoke()方法 TestBean tb3 = clazz.newInstance(); Method method1 = clazz.getDeclaredMethod("setName", String.class); Method method2 = clazz.getDeclaredMethod("setAge", int.class); method1.invoke(tb3, "玄德"); method2.invoke(tb3, 66); System.out.println(tb3.getName() + tb3.getAge() + "歲"); // 通過(guò)反射操作屬性 TestBean tb4 = clazz.newInstance(); Field f1 = clazz.getDeclaredField("name"); Field f2 = clazz.getDeclaredField("age"); // 報(bào)錯(cuò)不能訪問(wèn)私有屬性的解決方法(屬性可以設(shè)置,方法也可以這樣設(shè)置) f1.setAccessible(true); f2.setAccessible(true); f1.set(tb4, "紫龍"); f2.set(tb4, 33); System.out.println(tb4.getName() + f2.get(tb4) + "歲"); } catch (Exception e) { e.printStackTrace(); } } }
反射機(jī)制的性能
setAccessible
是訪問(wèn)安全檢查的開關(guān)。設(shè)置true表示反射的對(duì)象在使用時(shí)應(yīng)該取消Java語(yǔ)言訪問(wèn)檢查。
禁止安全檢查可以提高反射的運(yùn)行速度。
可以考慮使用cglib/javaassist字節(jié)碼操作提升反射操作的速度。
反射操作泛型(Generic)
Java使用泛型擦除機(jī)制來(lái)引入泛型。Java中的泛型僅僅是給編譯器javac使用的。泛型用于確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換帶來(lái)的不便。Java一旦編譯完成,所有和泛型有關(guān)的類型將全部擦除。
Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType幾種類型來(lái)代表不能被歸一到Class類中的類型,但又和原始類型保持一致。
ParameterizedType:表示一種參數(shù)化的類型,比如:Collection
GenericArrayType:表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
TypeVariable:是各種類型變量的公共父接口
WildcardType:代表一種通配符類型表達(dá)式,比如:?,? extends Number,? super Integer。
import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; public class Test { public void test1(Mapmap, List list) { System.out.println("Test.test1()"); } public Map test2() { System.out.println("Test.test2()"); return null; } public static void main(String[] args) { try { // 獲得指定方法參數(shù)泛型信息 Method m = Test.class.getMethod("test1", Map.class, List.class); Type[] t = m.getGenericParameterTypes(); for (Type type : t) { System.out.println("#" + type); if (type instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments(); for (Type genericType : genericTypes) { System.out.println("泛型類型:" + genericType); } } } System.out.println("-------------------"); // 獲得指定方法返回值泛型信息 Method m2 = Test.class.getMethod("test2", null); Type returnType = m2.getGenericReturnType(); System.out.println("#" + returnType); if (returnType instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type type : genericTypes) { System.out.println("返回值泛型類型:" + type); } } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } }
關(guān)于“java反射機(jī)制怎么實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。