1、在编译的时候不确定用哪个属性或方法时,则可以使用反射。
2、getDeclared系列方法:
- 可以获取当前运行时类及其父类中声明为 public 访问权限的属性或方法;
- 获取当前运行时类中声明为 public 的构造器(不包含父类)
3、非Declared系列方法:
- 可以获取当前运行时类中声明的所有属性、方法或构造器(不包含父类);当遇到私有结构时,先执行 setAccessible(true) 方法就可以访问了,否则会报错。
java">public class Person {
private String name;
public int age;
public String nation;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String nation) {
this.name = name;
this.age = age;
this.nation = nation;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getNation() {
return nation;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setNation(String nation) {
this.nation = nation;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", nation='" + nation + '\'' +
'}';
}
public void show() {
System.out.println(this);
}
}
java">import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
// Person p1 = new Person("Tom", 12, "中国");
//通过反射,创建运行时类对象
Class clazz = Person.class;// or Class<Person> clazz = Person.class;
Constructor cons = clazz.getConstructor(String.class, int.class);
Person p1 = (Person) cons.newInstance("Tom", 14);
System.out.println(p1);
//getConstructors(): 获取当前运行时类中声明为public的构造器(不包含父类构造器)
Constructor[] constructors = clazz.getConstructors();
for (Constructor c: constructors) {
System.out.println(c);
}
//getDeclaredConstructors(): 获取当前运行时类中声明的所有构造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor c: declaredConstructors) {
System.out.println(c);
}
//getFields(): 获取当前运行时类及其父类中声明为public访问权限的属性
Field[] fields = clazz.getFields();
for (Field f: fields) {
System.out.println(f);
}
//getDeclaredFields(): 获取当前运行时类中声明的所有属性(不包含父类)
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f: declaredFields) {
System.out.println(f);
}
//getDeclaredField(属性名称): 通过反射,调用对象指定的属性
Field age = clazz.getDeclaredField("age");
if(!age.isAccessible()) {
age.setAccessible(true);//设置为可访问,否则私有属性不可访问
}
age.set(p1, 10);
System.out.println(p1);
//getMethods(): 获取当前运行时类及其父类中声明为public访问权限的方法
Method[] methods = clazz.getMethods();
for (Method method: methods) {
System.out.println(method);
}
//getDeclaredMethods(): 获取当前运行时类中声明的所有方法(不包含父类)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method: declaredMethods) {
System.out.println(method);
}
//getDeclaredMethod(方法名称): 通过反射,调用对象指定的方法
Method show = clazz.getDeclaredMethod("show");
if(!show.isAccessible()){
show.setAccessible(true);//设置为可访问,否则私有方法不可访问
}
show.invoke(p1);
//获取类实例的4种方式
//方式一:.class(有限制:编译时就把要调用的类名确定了)
Class clazz1 = Person.class;
System.out.println(clazz1);//class reflectTest.Person
//方式二:通过运行时类对象(有限制:提前是本身就有该类的对象)
Person p = new Person("Tom", 12);
Class clazz2 = p.getClass();
System.out.println(clazz2);//class reflectTest.Person
//方式三:调用class的静态方法(常用)
Class clazz3 = Class.forName("reflectTest.Person");
System.out.println(clazz3);//class reflectTest.Person
//方式四:使用类的加载器:ClassLoader(不常用)
ClassLoader classLoader = ReflectTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("reflectTest.Person");
System.out.println(clazz4);//class reflectTest.Person
}
}