Java通过反射调用类中的指定方法、指定属性、指定构造器
1.调用指定方法
通过反射,调用类中的方法,通过Method类完成。步骤:
- 通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
- 之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
Object invoke(Object obj, Object … args),说明
- Object 对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法若为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
2. 调用指定属性
在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。
- public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
- public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
- 在Field中:
- public Object get(Object obj) 取得指定对象obj上此Field的属性内容
- public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
3. 调用指定构造器
在反射机制中,可以通过获取运行时类的构造器的方法,并指定构造器属性,来指定构造器;
- public Constructor getConstructor(Class … parameterTypes):获取声明为public的指定构造器
- public Constructor getDeclaredConstructor(Class … parameterTypes):获取运行时类中声明的指定的构造器
注:在类中属性都设置为private的前提下,在使用set()和get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。
public void setAccessible(true)访问私有属性时,让这个属性可见。
//调用运行时类中指定的方法
@Test
public void test3() throws Exception {
Class clazz = Person.class;
//getMethod(String methodName,Class ... params):获取运行时类声明为public的方法
Method m1 = clazz.getMethod("show");
Person p = (Person)clazz.newInstance();
//调用指定的方法:Object invoke(Object obj,Object ... obj)
Object returnVal = m1.invoke(p);//I am person
System.out.println(returnVal);//null
Method m2 = clazz.getMethod("toString");
Object returnVal2 = m2.invoke(p);
System.out.println(returnVal2);//Person [name=null, age=0]
//对于静态方法的调用
Method m3 = clazz.getMethod("info");
m3.invoke(Person.class);//Chinese
//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明的指定的方法
Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class);
m4.setAccessible(true);//私有方法需要注意权限
Object value = m4.invoke(p, "CHN",10);//我的国籍是:CHN
System.out.println(value);//10
}
//调用运行时类中指定的属性
@Test
public void test3() throws Exception {
Class clazz = Person.class;
//1.获取指定的属性
//getField(String name):获取运行时类声明为public的指定属性名为fieldName的属性
Field name = clazz.getField("name");
//2.创建运行时类的对象
Person p = (Person)clazz.newInstance();
System.out.println(p);//Person [name=null, age=0]
//3.将运行类指定的属性赋值
name.set(p, "Jerry");
System.out.println(p);//Person [name=Jerry, age=0]
System.out.println();
//getDeclaredField(Strin fieldName):获取运行时类中指定的的名为:fieldName的属性
Field age = clazz.getDeclaredField("age");
//由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得属性可以被操作
age.setAccessible(true);//设置为可访问的
age.set(p, 10);
System.out.println(p);//Person [name=Jerry, age=10]
// Field id = clazz.getField("id");
}
//获取指定的构造器,创建运行时类的对象
@Test
public void test3() throws Exception {
String className = "testReflection.Person";
Class clazz = Class.forName(className);
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p = (Person)cons.newInstance("Jhon",20);
System.out.println(p);//Person [name=Jhon, age=20]
}
@MyAnnotation("person")
public class Person extends Creature<String> implements Comparable<Object>,MyInterface {
public String name;
private int age;
int id;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
...
@MyAnnotation(value = "abc")
public void show() {
System.out.println("I am a person");
}
private Integer display(String nation,Integer i) throws Exception{
System.out.println("我的国籍是:"+ nation);
return i;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(Object o) {
return 0;
}
public static void info() {
System.out.println("Chinese");
}
class Bird{
}
}