以下测试使用Student类,属性和方法如下所示:
import lombok.Data;
@Data
public class Student {
private Integer id;
private String name;
public Student() {
System.out.println("无参构造方法");
}
public Student(Integer id, String name) {
this.id = id;
this.name = name;
System.out.println("有参构造方法");
}
private String stuTest(Integer a) {
System.out.println("stuTest方法" + a);
return "stuTest";
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
一、实例化对象
步骤
- 获取class对象
- 使用无参构造
- 使用
Class.newInstance()
实例化对象
- 使用
- 使用有参构造
- 获取有参构造器
- 使用
Constructor.newInstance()
实例化对象
示例
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException,
IllegalAccessException,
InstantiationException,
NoSuchMethodException,
InvocationTargetException {
Class<?> aClass = Class.forName("com.example.study.reflection.Student");
Student student = (Student) aClass.newInstance(); //使用无参构造
System.out.println(student);
//使用有参构造函数初始化
Constructor<?> constructor = aClass.getConstructor(Integer.class, String.class);
Student zhangsan = (Student) constructor.newInstance(1, "zhangsan");
System.out.println(zhangsan);
}
}
结果:
无参构造方法
Student{id=null, name='null'}
有参构造方法
Student{id=1, name='zhangsan'}
二、字段
1.api
- Class.getField(String name)
- Class.getFields()
- Class.getDeclaredField(String name)
- Class.getDeclaredFields()
注:前两个方法只能获取当前类
及其父类
的public
字段,后两个方法能获取当前类
的所有修饰符修饰的
字段
2.示例
测试前,先在Student加上了public修饰的变量:
public Integer test;
import java.lang.reflect.Field;
public class Test02 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.example.study.reflection.Student");
Field test = aClass.getField("test");
System.out.println(test);
System.out.println("--------------------------");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("--------------------------");
Field id = aClass.getDeclaredField("id");
System.out.println(id);
System.out.println("--------------------------");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("--------------------------");
}
}
结果:
public java.lang.Integer com.example.study.reflection.Student.test
--------------------------
public java.lang.Integer com.example.study.reflection.Student.test
--------------------------
private java.lang.Integer com.example.study.reflection.Student.id
--------------------------
private java.lang.Integer com.example.study.reflection.Student.id
private java.lang.String com.example.study.reflection.Student.name
public java.lang.Integer com.example.study.reflection.Student.test
--------------------------
3.给字段赋值步骤:
- 获取字段
- 实例化对象
- 赋值
Student student = (Student) aClass.newInstance();
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(student, "张三");
注:field.setAccessible(true)
是为了关闭对该字段的权限检查,如果该字段是用private
修饰的,不关闭则无法访问。
三、方法
1.api
- Class.getMethod(String name, Class<?> parameterTypes)
- Class.getMethods()
- Class.getDeclaredMethod(String name, Class<?> parameterTypes)
- Class.getDeclaredMethods()
2.使用
获取类的方法过程与获取字段类似,可参考字段的示例
3.调用获取的方法
- method.invoke(Object object, Object… args)
第一个参数为实例化对象
,后面的参数为调用的方法的参数
,如果无参数,可以不填,或者使用null,例如:
stuTest.setAccessible(true); //stuTest方法是私有的
String invoke = (String) stuTest.invoke(student, 9); //student是实例化对象,9为方法参数