Java注解和反射04:获取类的运行时结构
获取运行时类的完整结构
通过反射可以获得类实现的接口、父类、构造器、方法、属性、注解
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class<?> c1 = Class.forName("Test");
/**
* getName()方法获得类名
*/
System.out.println(c1.getName());
System.out.println();
/**
* getDeclaredFields()方法获得所有属性,包括私有属性
* getFields()方法只能获得所有public属性
*/
Field[] fields = c1.getDeclaredFields();
for (Field field : fields){
System.out.println(field);
}
System.out.println();
/**
* getDeclaredField()方法获得指定属性,包括私有属性
*/
Field field = c1.getDeclaredField("name");
System.out.println(field);
System.out.println();
/**
* getDeclaredMethods()方法获得本类的所有方法,包括私有方法
* getMethods()方法获得本类和父类的所有public方法
*/
Method[] methods = c1.getDeclaredMethods();
for (Method method : methods){
System.out.println(method);
}
System.out.println();
/**
* getDeclaredMethod()方法获得指定方法,包括私有方法
* 如果由参数,需要传入参数类型对应的Class对象
*/
Method method = c1.getDeclaredMethod("test", String.class);
System.out.println(method);
System.out.println();
/**
* getDeclaredConstructors()方法获得所有构造器,包括私有构造器
* getConstructors()方法只能获得public构造器
*/
Constructor[] constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
System.out.println();
/**
* getDeclaredConstructor()方法获得指定构造器,包括私有构造器
* 需要传入参数类型对应的Class对象
*/
Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println(constructor);
}
}
class Test {
private String name;
int age;
int money;
public Test(){}
private Test(String name, int age, int money){
this.name = name;
this.age = age;
this.money = money;
}
private void test(String name) {
System.out.println(name + "的test()方法");
}
private void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", age=" + age +
", money=" + money +
'}';
}
}
创建运行时类的对象、调用运行时类的指定结构
- 调用Class对象的newInstance()方法,创建运行时类的对象
- 如果有无参构造器且权限足够,可以直接创建对象,属性为默认值
- 如果没有无参构造器,需要用getDeclaredConstructor()方法获得指定的有参构造器,传入参数类型对应的Class对象,再通过Constructor实例化对象
- Method、Field、Constructor对象都有setAccessible()方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> c1 = Class.forName("Test");
/**
* 创建对象
* 默认调用无参构造器的newInstance()方法创建对象,需要强制转换一下类型
*/
Test test = (Test) c1.newInstance();
System.out.println(test);
/**
* 没有无参构造器,可以调用指定的有参构造器创建对象
* 先获得一个有参构造器对象,再创建对象
* 如果是私有构造器,需要用setAccessible(true)方法关闭程序的安全检测
*/
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
constructor.setAccessible(true);
Test test2 = (Test) constructor.newInstance("ty", 24, 10000);
System.out.println(test2);
/**
* 调用方法
* 先获得一个指定方法的对象,再通过invoke()方法激活要调用的方法
* 如果是私有方法,需要用setAccessible(true)方法关闭程序的安全检测
*/
Method method = c1.getDeclaredMethod("setName", String.class);
method.setAccessible(true);
method.invoke(test2, "ttyy");
System.out.println(test2.getName());
/**
* 操作属性
* 先获得一个指定属性的对象,再通过set()方法修改属性
* 如果是私有属性,需要用setAccessible(true)方法关闭程序的安全检测
*/
Field field = c1.getDeclaredField("name");
field.setAccessible(true);
field.set(test2, "tttyyy");
System.out.println(test2.getName());
}
}
class Test {
private String name;
int age;
int money;
public Test(){}
private Test(String name, int age, int money){
this.name = name;
this.age = age;
this.money = money;
}
private void test(String name) {
System.out.println(name + "的test()方法");
}
private void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", age=" + age +
", money=" + money +
'}';
}
}