java反射 之前学过反射,半知半解,今天重新学习一下Java反射机制,以及能做的事情。
下面是反射获取类Test的的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import java.io.IOException;import java.lang.Runtime;public class Test { public static final int h = 5 ; public String s = "test" ; public static final boolean b = new Boolean (false ); public Test () { System.out.println("无参构造函数" ); } public Test (int m, double n) throws IOException { System.out.println("有参构造函数" ); System.out.println("获取到int=" +m); System.out.println("获取到double=" +n); Runtime.getRuntime().exec("open /System/Applications/Calculator.app" ); } public String hello (String s) { System.out.println("调用hello" ); return "Hello World~" ; } public int hello2 (int x,double y) throws IOException { System.out.println("获取到int=" +x); System.out.println("获取到double=" +y); Runtime.getRuntime().exec("open /System/Applications/Calculator.app" ); return 3 ; } }
反射创建对象实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class Test_Reflect_getConstructor { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class c = Class.forName("Test" ); Constructor ct1 = c.getConstructor(); Test obj = (Test)ct1.newInstance(); obj.hello("test" ); Class partypes[] = new Class [2 ]; partypes[0 ] = Integer.TYPE; partypes[1 ] = Double.TYPE; Constructor ct2 = c.getConstructor(partypes); Object arglist[] = new Object [2 ]; arglist[0 ] = new Integer (37 ); arglist[1 ] = new Double (47.0 ); Object obj2 = ct2.newInstance(arglist); } }
反射获取类方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.lang.reflect.Method;public class Test_Reflect_methods {public static void main (String[]args) throws ClassNotFoundException { Class c = Class.forName("java.lang.Runtime" ); Method methods[] = c.getDeclaredMethods(); for (int i = 0 ; i < methods.length; i++) { Method m = methods[i]; Class pvec[] =m.getParameterTypes(); System.out.println("方法=" +m.getName()); for (int q = 0 ; q < pvec.length; q++) { System.out.println("参数类型" +pvec[q].getName()); } System.out.println("返回类型=" +m.getReturnType()); System.out.println("-----------------------------" ); } } }
获取字段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.lang.reflect.Field;import java.lang.reflect.Modifier;public class Test_Reflect_field { public static void main (String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class c = Class.forName("Test" ); Field fieldlist[] = c.getDeclaredFields(); for (int i = 0 ; i < fieldlist.length; i++) { fieldlist[i].setAccessible(true ); System.out.println("字段名=" +fieldlist[i].getName()); System.out.println("字段值=" +fieldlist[i].get(c.newInstance())); System.out.println("字段类型=" +fieldlist[i].getType()); int mod = fieldlist[i].getModifiers(); System.out.println("声明类型=" + Modifier.toString(mod)); System.out.println("----------------------------" ); } } }
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 字段名=h 无参构造函数 字段值=5 字段类型=int 声明类型=public static final ---------------------------- 字段名=s 无参构造函数 字段值=test 字段类型=class java.lang.String 声明类型=public ---------------------------- 字段名=b 无参构造函数 字段值=false 字段类型=boolean 声明类型=public static final ----------------------------
修改字段 反射修改注意如果是static final修饰的,需要先去掉final,再次进行修改,还需要注意,static final修饰的直接赋值还是间接赋值,直接赋值只能通过反射获取修改后的数据(编译优化导致)。间接赋值的可以直接获取修改后的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Modifier;public class Test_Reflect_Set_field { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException { Class c = Class.forName("Test" ); Field field[] = c.getDeclaredFields(); Test obj = (Test) c.newInstance(); for (int i = 0 ; i < field.length; i++) { System.out.println("修改前的值" +field[i].getName()+"=" +field[i].get(obj)+" 类型为 " +Modifier.toString(field[i].getModifiers())); } System.out.println("------------------" ); field[0 ].setAccessible(true ); Field modifiers = field[0 ].getClass().getDeclaredField("modifiers" ); modifiers.setAccessible(true ); modifiers.setInt(field[0 ], field[0 ].getModifiers() & ~Modifier.FINAL); field[0 ].set(obj, 10 ); System.out.println("反射修改后直接获取" +field[0 ].getName()+"=" +obj.h); System.out.println("反射修改后反射获取" +field[0 ].getName()+"=" +field[0 ].get(obj)); System.out.println("--------------------" ); field[1 ].setAccessible(true ); modifiers.setInt(field[1 ], field[1 ].getModifiers() & ~Modifier.FINAL); field[1 ].set(obj, "hack" ); System.out.println("反射修改后直接获取" +field[1 ].getName()+"=" +obj.s); System.out.println("反射修改后反射获取" +field[1 ].getName()+"=" +field[1 ].get(obj)); System.out.println("--------------------" ); field[2 ].setAccessible(true ); modifiers.setInt(field[2 ], field[2 ].getModifiers() & ~Modifier.FINAL); field[2 ].set(obj, true ); System.out.println("反射修改后直接获取" +field[2 ].getName()+"=" +obj.b); System.out.println("反射修改后反射获取" +field[2 ].getName()+"=" +field[2 ].get(obj)); } }
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 无参构造函数 修改前的值h=5 类型为 public static final 修改前的值s=test 类型为 public 修改前的值b=false 类型为 public static final ------------------ 反射修改后直接获取h=5 反射修改后反射获取h=10 -------------------- 反射修改后直接获取s=hack 反射修改后反射获取s=hack -------------------- 反射修改后直接获取b=true 反射修改后反射获取b=true
调用方法 常规类调用方法 常规类调用方法流程为获取类、创建实例、执行方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test_Reflect_Get_methods { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class c = Class.forName("Test" ); Class partypes[] = new Class [2 ]; partypes[0 ] = Integer.TYPE; partypes[1 ] = Double.TYPE; Method meth = c.getMethod("hello2" , partypes); Test test = new Test (); Object arglist[] = new Object [2 ]; arglist[0 ] = new Integer (3 ); arglist[1 ] = new Double (3.1 ); Object ref = meth.invoke(test, arglist); System.out.println(ref); } }
单例类调用方法 单例模式的特点
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。
java.lang.Runtime就是一个单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Runtime { private static Runtime currentRuntime = new Runtime (); public static Runtime getRuntime () { return currentRuntime; } private Runtime () {}
Runtime的Runtime.exec调用 注意点,invoke作用是执行方法,第一个参数为:
如果是普通方法执行invoke,第一个参数放对象的实例;
如果是静态方法执行invoke,可以放null或类名;
放调用代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test_Reflect_Get_methods { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Class c = Class.forName("java.lang.Runtime" ); Method method = c.getDeclaredMethod("exec" , String.class); Method method1 = c.getDeclaredMethod("getRuntime" ); Object obj = method1.invoke(null ); method.invoke(obj, "open /System/Applications/Calculator.app" ); } }