参考:JAVA反射之调用方法
java反射前及反射后类的实例化等操作
一、反射 调用方法
1.1 获得 Method 对象
我们已经能通过Class实例获取所有Field对象,同样的,可以通过Class实例获取所有Method信息。Class类提供了以下几个方法来获取Method:
Method getMethod(name, Class...):获取某个public的Method(包括父类)
Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
Method[] getMethods():获取所有public的Method(包括父类)
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
public class Main {
public static void main(String[] args) throws Exception {
Class stdClass = ;
// 获取public方法getScore,参数为String:
(("getScore", ));
// 获取继承的public方法getName,无参数:
(("getName"));
// 获取private方法getGrade,参数为int:
(("getGrade", ));
}
}
class Student extends Person {
public int getScore(String type) {
return 99;
}
private int getGrade(int year) {
return 1;
}
}
class Person {
public String getName() {
return "Person";
}
}
public int ()
public ()
private int (int)
Method 对象的信息获取:
一个Method对象包含一个方法的所有信息:
getName():返回方法名称,例如:"getScore";
getReturnType():返回方法返回值类型,也是一个Class实例,例如:;
getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{, };
getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
1.2 调用非静态方法
先得到 Method 对象 然后再调用 invoke 方法
当我们获取到一个Method对象时,就可以对它进行调用。我们以下面的代码为例:
String s = "Hello world";
String r = (6); // "world"
如果用反射来调用substring方法,需要以下代码:
// reflection
import ;
public class Main {
public static void main(String[] args) throws Exception {
// String对象:
String s = "Hello world";
// 获取String substring(int)方法,参数为int:
Method m = ("substring", );
// 在s对象上调用该方法并获取结果:
String r = (String) (s, 6);
// 打印调用结果:
(r);
}
}
对Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。
1.3 调用静态方法
如果获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null。我们以(String)为例:
// reflection import ;
public class Main {
public static void main(String[] args) throws Exception {
// 获取(String)方法,参数为String:
Method m = ("parseInt", );
// 调用该静态方法并获取结果:
Integer n = (Integer) (null, "12345");
// 打印调用结果:
(n);
}
}
1.4 调用非 public 方法
和Field类似,对于非public方法,我们虽然可以通过()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过(true)允许其调用:仍然可能失败
// reflection
import ;
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
Method m = ().getDeclaredMethod("setName", );
(true);
(p, "Bob");
();
}
}
class Person {
String name;
private void setName(String name) {
= name;
}
}
1.5 多态
我们来考察这样一种情况:一个Person类定义了hello()方法,并且它的子类Student也覆写了hello()方法,那么,从获取的Method,作用于Student实例时,调用的方法到底是哪个?
使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)。