一、什么是反射
反射首先是能够获取到Java中的反射类的字节码,然后将字节码中的方法,变量,构造函数等映射成 相应的 Method、Filed、Constructor 等类
二、反射的API
获取class字节码对象 的3 种方法
//第一种
Class studentClass = Student.class;
//第二种
Student student = new Student();
Class studentClass1 = student.getClass();
//第三种 必须为全路径
Class studentClass2 = Class.forName("com.example.service.Impl.Student");
常用的一些API
获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名
获取成员变量定义信息
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)
获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)
获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)
反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法
反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法
三、示例
首先定义一个类
@Data
@Builder
@Service
public class Student {
public String name;
private int age;
public char egx;
protected Integer phone;
Student(String name ,int age,char egx,Integer phone){
System.out.println("默认的构造方法");
}
public Student(){
System.out.println("调用无参构造方法。。。。。");
}
public Student(String name){
this.name = name;
System.out.println("name:"+name);
}
public Student(String name,int age){
System.out.println("name:"+name+","+"age:"+age);
}
private Student(int age){
System.out.println("私有的构造方法");
}
protected Student(boolean b){
System.out.println("受保护的构造方法");
}
public String get(){
return "调用方法";
}
public String getMethod(String string){
return string + "是个大学老师!";
}
}
获取构造方法
/*
* 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
*
* 1.获取构造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
*
* 调用构造方法:
* Constructor-->newInstance(Object... initargs)
*/
System.out.println("==================调用构造方法=====================");
Class clazz = Student.class;
//类路径
System.out.println(clazz.getName());
//获取所有的公共构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
//获取所有的构造方法 包含私有的受保护的
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors){
System.out.println(constructor);
}
//获取 公共的参数为String的构造方法
Constructor constructor = clazz.getConstructor(String.class);
System.out.println(constructor);
//获取公共的无参构造方法
Constructor constructor1 = clazz.getConstructor(null);
System.out.println(constructor1);
Object o = constructor1.newInstance();
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
//暴力访问,忽略掉访问修饰符
declaredConstructor.setAccessible(true);
Object object = declaredConstructor.newInstance("男");
获取成员变量并调用:
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
System.out.println("=====================获取字段参数=====================");
Class clazz = Class.forName("com.example.service.Impl.Student");;
//获取所有公共参数
Field[] fields = clazz.getFields();
for(Field field : fields){
// System.out.println(field);
}
//获取所有参数
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields){
System.out.println(field);
}
//获取 name 参数
Field name = clazz.getField("name");
// Student s = new Student();
Object o = clazz.getConstructor(null).newInstance();
//给name 参数 赋值
name.set(o,"黄磊");
Student s = (Student)o;
System.out.println("验证名字:"+s.getName());
//获取私有参数
Field phone = clazz.getDeclaredField("phone");
//暴力访问,忽略掉访问修饰符
phone.setAccessible(true);
//第一个参数为设置的对象,第二个参数为要传入的实参
//等同与student.setPhone(12356789)
phone.set(o,123456789);
System.out.println("验证电话:"+s.getPhone());
获取方法并调用
System.out.println("=====================获取方法=======================");
Class clazz = Student.class;
//获取所有公共的方法
Method[] methods = clazz.getMethods();
//获取所以方法 包含私有的,受保护的
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods){
System.out.println(method.getName());
}
Method getMethod = clazz.getMethod("getMethod",String.class);
//无参初始化
Object o1 = clazz.newInstance();
//执行方法为私有的 得先设置私有可见
getMethod.setAccessible(true);
//传入参数,执行方法
Object o = getMethod.invoke(o1,"ww");
System.out.println(o.toString());