相关概念:
反射:Java独有的技术
作用:对于任何一个类,在运行时都可以直接得到这个类的全部成分
构造器对象Constructor,成员变量对象Filed,成员方法对象Method
核心思想:得到编译后的class文件对象
注意:反射是工作在运行时的技术,因为只有在运行后才有class类对象
反射的第一步永远是先得到Class类对象,有3种方式
(1)类名.class
(2)通过类的对象.getClass()
(3)Class.forName("类的全限定名")
获取构造器:
public Constructor<T> getConstructor(Class<?>... parameterTypes) 根据参数匹配获取某个构造器,只能获取public修饰的构造器
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 根据参数匹配获取某个构造器,不关心权限修饰符
public Constructor<?>[] getConstructors() 获取全部构造器,只能是public修饰
public Constructor<?>[] getDeclaredConstructors() 获取全部构造器,不关心权限修饰符
构造器初始化对象方法:
public T newInstance(Object ... initargs) 调用无参数构造器,已弃用
public void setAccessible(boolean flag) 修改访问权限,单次有效
获取成员变量:
public Field getField(String name) 根据成员变量名获取对应Field对象,只能获取public修饰,包括父类
public Field getDeclaredField(String name) 根据成员变量名获取对应Field对象,只要定义就能获取
public Field[] getFields() 获取所有成员变量的Field对象,只能获取public修饰,包括父类
public Field[] getDeclaredFields() 获取所有成员变量的Field对象,只要定义就能获取
成员变量的方法:
public void set(Object obj, Object value) 设置obj的成员变量值为value
public Object get(Object obj) 获取obj的成员变量值
public void setAccessible(boolean flag) 修改访问权限
public Class<?> getType() 获取成员变量的类型
public String getName() 获取成员变量名称
获取方法
public Method getMethod(String name,Class<?>... parameterTypes) 根据方法名和参数获取对应Method对象,只能获取public修饰,包括父类
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 根据方法名和参数获取对应Method对象,只要定义就能获取
public Method[] get Methods() 获取所有方法的Method对象,只能获取public修饰,包括父类
public Method[] getDeclaredMethods() 获取所有方法的Method对象,只要定义就能获取
Method相关方法:
public Object invoke(Object obj, Object... args) 使obj对象执行某方法,没有返回值返回null
反射可以破坏面向对象的封装性,同时可以破坏泛型的约束性(泛型只能工作在编译阶段)
要存储的Student类:
class Student{
private String name;
private int age;
private char sex;
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
存储方法和测试方法:
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Student student = new Student("kobe", 40, '男');
save(student);
}
public static void save(Object obj){
try(PrintStream ps=new PrintStream(new FileOutputStream("heima/src/day12_junit_反射_注解_代理/data.txt"),true)){
//获取Class对象
Class<?> clazz = obj.getClass();
ps.println("---------"+clazz.getSimpleName()+"---------");
//获取所有成员变量
Field[] fields = clazz.getDeclaredFields();
for(Field field:fields){
//成员变量名
String fieldName = field.getName();
//成员变量对应的get方法名称=get+首字母大写的成员变量名
String methodName="get"+fieldName.toUpperCase().substring(0,1)+fieldName.substring(1);
Method method = clazz.getDeclaredMethod(methodName);
//成员变量对应的值
Object value = method.invoke(obj);
//save
ps.println(fieldName+"="+value);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
结果: