※屬性設值取值
package inheritate; public class Son { public String s1; private String s2; } ------------------------------ public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("inheritate.Son"); Field s1 = clazz.getField("s1"); Object s1Obj = clazz.newInstance(); s1.set(s1Obj, "xxx"); System.out.println(s1.get(s1Obj)); // Field s2 = clazz.getField("s2"); Field s2 = clazz.getDeclaredField("s2"); s2.setAccessible(true); Object s2Obj = clazz.newInstance(); s2.set(s2Obj, "ooo"); System.out.println(s2.get(s2Obj)); }
※修飾子不是public的,有可能會報「NoSuchFieldException」的錯,得看測試類在放在哪而定
※想取得上面報的錯的值,可用setAccessible,但得用DeclaredField才行,不然還是會報錯,因為DeclaredField本來就是取自己class的東西
※AccessibleObject.setAccessible
Field和Method到最後都會繼承AccessibleObject類別,所以setAccessible都可以用setAccessible是個overloadding,有分一個參數和兩個參數,兩個參數是static的
一個參數上個例子已有,這裡講的是兩個參數的
package inheritate; public class Son { private String s0; private String s1; private String s2; private String s3; private String s4; } ------------------------------ public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("inheritate.Son"); Field[] fields = clazz.getDeclaredFields(); Object obj = clazz.newInstance(); for (int i = 0; i < fields.length; i++) { fields[i].setAccessible(true); fields[i].set(obj, "s" + i); System.out.println("field name=" + fields[i].getName()); System.out.println("field value=" + fields[i].get(obj)); System.out.println(); } }
※這個例子還是和上個例子一樣,跑迴圈時,一個一個變成true
※
Class<?> clazz = Class.forName("inheritate.Son"); Field[] fields = clazz.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); Object obj = clazz.newInstance(); for (int i = 0; i < fields.length; i++) { // f.setAccessible(fields, true); fields[i].set(obj, "s" + i); System.out.println("field name=" + fields[i].getName()); System.out.println("field value=" + fields[i].get(obj)); System.out.println(); }
※使用靜態方法可以一次將屬性全部變成true
※註解那行也是可以,但浪費一些資源,而且會有警告,因為它是static
※方法設值取值
package inheritate; public class Son { public String sayHello() { return "hello"; } public String say(String data) { return data; } private String privateTest() { return "private method"; } } ------------------------------ public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("inheritate.Son"); // 呼叫無參方法 Method m1 = clazz.getMethod("sayHello"); String r1 = (String) m1.invoke(clazz.newInstance()); System.out.println(r1); // 呼叫有參方法 Method m2 = clazz.getMethod("say", String.class); String r2 = (String) m2.invoke(clazz.newInstance(), "Hello Reflection"); System.out.println(r2); // 取得private方法 // Method m3 = clazz.getMethod("privateTest"); Method m3 = clazz.getDeclaredMethod("privateTest"); m3.setAccessible(true); String r3 = (String) m3.invoke(clazz.newInstance()); System.out.println(r3); }
※修飾子不是public的,有可能會報「NoSuchMethodException」的錯,得看測試類在放在哪而定
※想取得上面報的錯的值,可用setAccessible,但得用DeclaredMethod才行,不然還是會報錯,因為DeclaredField本來就是取自己class的東西
※invoke就是呼叫方法了,裡面至少要放實體,如果沒有回傳值也不會報錯,會回傳null
※setter/getter
package inheritate; public class Son { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } ------------------------------ public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("inheritate.Son"); Object obj = clazz.newInstance(); Class<?> cz = obj.getClass(); Method m1 = cz.getMethod("setId", int.class); m1.invoke(obj, 1); Method m2 = cz.getMethod("getId"); Object getResult = m2.invoke(obj); System.out.println(getResult); }
※使用newInstance取得實體,然後再取得Class,這個Class可以讓setter/getter使用
※setter/getter公用方法
public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("inheritate.Son"); Object obj = clazz.newInstance(); Class<?> cz = obj.getClass(); setXxx(cz, obj, "id", int.class, 1); int rtn = (int) getXxx(cz, obj, "id"); System.out.println(rtn); } public static <T> void setXxx(Class<?> sourceClass, Object instance, String methodName, Class<T> parameterType, T value) throws Exception { Method m = sourceClass.getMethod("set" + firstUpperCase(methodName), parameterType); m.invoke(instance, value); } public static String firstUpperCase(String methodName) { return methodName.substring(0, 1).toUpperCase() + methodName.substring(1); } public static Object getXxx(Class<?> sourceClass, Object instance, String methodName) throws Exception { Method m = sourceClass.getMethod("get" + firstUpperCase(methodName)); return m.invoke(instance); }
※
沒有留言:
張貼留言