反射机制
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
下面是我们用于测试反射机制的Person类:
package entity;
public class Person {
private String name;
protected int age;
public String sex;
public Person() {
}
private Person(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
private void testPrivateMethod() {
System.out.println("testPrivateMethod被调用");
}
}
用于测试反射机制的demo
import entity.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionDemo {
public static void main(String[] args) throws Exception{
// getReflectionClass();
// getRelectionConstructors();
// getRelectionInstantiating();
// getRelectionFields();
getRelectionMethods();
}
public static void getReflectionClass() throws Exception {
/*---------------------
三种反射获得class实例的方法
---------------------*/
// 通过类的class获得Class实例
Class<Person> personClass = Person.class;
// 通过类的包名获得Class实例
Class<Person> personClass1 = (Class<Person>)Class.forName("entity.Person");
// 通过对象获得Class实例
Person person = new Person("x", 1);
Class<Person> personClass2 = (Class<Person>)person.getClass();
System.out.println("personClass = " + personClass);
System.out.println("personClass1 = " + personClass1);
System.out.println("personClass2 = " + personClass2);
}
public static void getRelectionConstructors() throws Exception {
/*---------------------
获取class中构造方法:
Constructor[] getDeclaredConstructors() 用于获取当前类中所有构造方法,不包括包括父类中的构造方法。
Constructor[] getConstructors() 用于获取本类中所有public修饰的构造方法,不包括父类的构造方法。
获取class中指定构造方法:
Constructor getDeclaredConstructor(Class<?>... parameterTypes) 该方法用来获取类中任意的构造方法,包括private修饰的构造方法。无法通过该方法获取到父类的构造方法。
Constructor getConstructor(Class<?>... parameterTypes) 该方法只能用来获取该类中public的构造方法。无法获取父类中的构造方法。
---------------------*/
Class<Person> personClass = Person.class;
/* getDeclaredConstructors() 获取所有类型 */
Constructor[] declaredConstructors1= personClass.getDeclaredConstructors();
System.out.println("declaredConstructor1:");
for(Constructor declaredConstructor:declaredConstructors1) {
System.out.println(declaredConstructor);
}
System.out.println("---------------------");
/* getConstructors() 只获取public修饰 */
Constructor[] declaredConstructors2= personClass.getConstructors();
System.out.println("declaredConstructor2:");
for(Constructor declaredConstructor:declaredConstructors2) {
System.out.println(declaredConstructor);
}
System.out.println("---------------------");
try {
// 按照参数配置来查找构造器
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor();
Constructor<Person> declaredConstructor2 = personClass.getDeclaredConstructor(String.class,int.class);
System.out.println("declaredConstructor = " + declaredConstructor);
System.out.println("declaredConstructor2 = " + declaredConstructor2);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getRelectionInstantiating() throws Exception {
/* ---------------------
通过Class的newInstance实例化对象,直接调用newInstance方法即可完成对象的实例化
使用Constructor实例化对象
--------------------- */
Class<Person> personClass = Person.class;
// newInstance只能实例化无参构造方法的类,同时这个无参构造方法不能使用private修饰。
// 否则会抛出异常。推荐使用Constructor来实例化对象
try {
Person person = personClass.newInstance();
System.out.println("person = " + person);
} catch (Exception e) {
e.printStackTrace();
}
// Constructor实例化对象
try {
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
// 通过Constructor实例化私有的构造方法时,需要通过Constructor的setAccessible(true)
// 来使Constructor可见(相当于临时将private变成public)
declaredConstructor.setAccessible(true);
Person x = declaredConstructor.newInstance("x", 1);
System.out.println(x.getName() + "---" + x.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getRelectionFields() throws Exception {
/* ---------------------
获取类的成员变量:
getDeclaredFields() 获取该类中所有成员变量,无法获取到从父类中继承的成员变量。
getFields() 获取类中所有public的成员变量,包括从父类中继承的public的成员变量。
--------------------- */
Class<Person> personClass = Person.class;
// 通过getDeclaredFields()来获取Person的成员变量,无论是用private修饰还是用public修饰
Field[] declaredFields = personClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.toString());
}
// getFields方法只获取Person类中public的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field.toString());
}
// 反射获取并修改类的成员变量
Person person = new Person("x", 1);
try {
System.out.println("反射修改前name为:" + person.getName());
// 获取Person中的私有成员变量name
Field name = personClass.getDeclaredField("name");
// 将name设置为可见
name.setAccessible(true);
// 修改person实例中name的值
name.set(person, "z");
System.out.println("反射修改后name为:" + person.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getRelectionMethods() throws Exception {
/* ---------------------
获取类的方法:
getDeclaredMethods() 获取本类中所有方法,不包括从父类中继承的方法。
getMethods() 获取类中所有public方法,包括从父类中继承的public方法。
--------------------- */
Class<Person> personClass = Person.class;
// getDeclaredMethods() 获取类中的所有方法,包括私有方法,但不包括父类中的方法。
Method[] declaredMethods = personClass.getDeclaredMethods();
// 遍历并打印方法信息
for (Method method :declaredMethods) {
System.out.println("getDeclaredMethods:"+method.toString());
}
System.out.println("---------------------");
// getMethods() 获取类中所有public方法,包括从父类中继承的public方法。
Method[] methods = personClass.getMethods();
// 遍历methods并打印方法信息
for (Method method : methods) {
System.out.println("getMethods:"+method.toString());
}
System.out.println("---------------------");
// 反射调用对象的私有方法testPrivateMethod
try {
// 获取Person类中的私有方法testPrivateMethod
Method testPrivateMethod = personClass.getDeclaredMethod("testPrivateMethod");
// 将testPrivateMethod方法设置为可见
testPrivateMethod.setAccessible(true);
// 反射调用testPrivateMethod方法
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
Person x = declaredConstructor.newInstance("x", 1);
testPrivateMethod.invoke(x);
} catch (Exception e) {
e.printStackTrace();
}
}
}