根据类名创建对象
要求:根据运行时得到的类名(字符串)创建对象。
创建的对象没有参数
Class<?> clazz = Class.forName("com.foo.BarClass"); Object date = clazz.newInstance();
创建对象需要参数
Class<?> clazz = Class.forName("com.foo.MyClass"); Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class); Object instance = constructor.newInstance("stringparam", 42);
参考:is there a way to instantiate a class by name in java?
执行方法调用
对于实例方法,也就是非static方法,用"obj.method()"方式调用,获得对象后可以按普通对象执行;对于静态(static)方法,需要用"ClassName.method()"方式调用,需要用到Java反射机制中的Method类,调用方法如下:
String className = "edu.princeton.cs.algs4.Selection"; Class<?> clazz = Class.forName(className); System.out.println("Loaded class: " + clazz); Method m = clazz.getDeclaredMethod("meth", new Class[] { int.class, int.class }); System.out.println("Got method: " + m); Object returnValue = m.invoke(null, 1, 5); // equals to "Selection.meth(1,5);" System.out.println("Return value of this method: " + returnValue);
被调用的Selection.meth()方法:
public static int meth(int i, int j) { System.out.println("result=" + (i + j + 10)); return i + j + 10; }
这里要注意的是:
-
className必须是包含包名的full name,
-
对于静态方法,m.invoke的第一个参数是null,如果是实例方法,第一个参数是执行这个方法的对象obj;
如何调用参数是数组的方法
例如有下面一个方法:
public static void sort(Comparable[] a) { int N = a.length; for (int i = 0; i < N; i++) { for (int j = i; j > 0 && less(a[j], a[j-1]); j--) { exch(a, j, j-1); } assert isSorted(a, 0, i); } assert isSorted(a); }
用反射调用这个方法要注意参数列表的写法:
Double[] a = new Double{1000];
Class<?> clazz = Class.forName(className); Method sortMethod = clazz.getDeclaredMethod("sort", Comparable[].class); Object[] param = { a }; sortMethod.invoke(null, param);
最后一行如果写为invoke(null, a)会报"wrong number of arguments error",原因是第3行的声明表明sort方法的参数只有一个,但Method.invoke方法的声明是:
Object invoke(Object obj, Object... args)
实际上就是invoke(Object obj, Object[] args),这样invoke(null, a)方法会给sort方法注入1000个参数(而不是a这个数组本身),解决方法就是专门声明param={a},然后invoke(null, param)。
参考:http://stackoverflow.com/questions/8189782/wrong-number-of-arguments-error-when-invoking-a-method