一、简介
反射技术:动态的获取类中的成员,并调用该类的成员。(也可以叫对类的解剖)
反射技术核心问题:要拿到类的字节码文件,即.class文件
字节码文件中会包含以下内容:
name(类名),constructor(构造器),field(字段),method(方法);
所以会有相应的获取这些内容的方法
getName();getConstructor();getField();getMethod();
描述字节码文件的类:Class
字节码文件只加载一次,即每个类在内存中只有一份.class文件
二、如何获取一个字节码文件的对象?
方式一:
Object中的getClass();该方法在反射技术里,不合适,必须有对象才能使用,反射中不明确具体类
Person p = new Person();
Class clazz = p1.getClass();
方式二:
所有的数据类型都有自己的Class对象,每一个数据类型都有一个默认的静态属性.class,可以用该属性获取到字节码文件对象
这个也必须要有对象才可以
int.class int类型的class对象
Person.class Person类型的class对象
方式三(重点掌握):
Class.forName(String name),通过名称获取对应的字节码文件对象。
Class.forName(String name):name必须加上包名
三、动态创建对象:
1.根据给定的类名获取Class对象
Class clazz = Class.forName(className);
创建一个对象
Object obj = clazz.newInstance();
newInstance()调用空参数构造函数,如果没有空参数构造函数就会抛出java.lang.InstationException
一般被反射的类通常都有空参数构造函数
2.根据指定的构造器动态创建对象:
先获取指定的构造函数
(1).通过Class获取指定的构造函数,比如带两个参数
Constructor cons = clazz.getConstructor(String.class,int.class);参数为类型对象
(2).动过指定的构造器对对象进行初始化
Object obj = cons.newInstance("zhangsan",19);
四、动态的获取字段
clazz.getFields():获取所有字段
clazz.getFields(String name):获取指定名称的字段
getXXX():只能拿到公有的,也就是public的
getDeclaredXXX():可以拿共有的和私有的,只要你声明,就会被拿到
例如:getDeclaredConstructor()
要对非静态的字段操作必须有对象
filed.set(obj,12);不能给private修饰的字符赋值
使用父类的方法将访问权限检查能力取消
filed.setAccessible(true);暴力访问
filed.set(obj,12);
五、动态获取方法
1.反射非静态无参数方法:
Method method = clazz.getMethod("methodName",null);
method.invoke(obj,null);调用方法
2.反射静态无惨方法:
Method method = clazz.getMethod("methodName",null);
method.invoke(null,null);调用方法
3.反射非静态有参数方法:
Method method = clazz.getMethod("methodName",String.class,int,class);
method.invoke(obj,"zhangsan",49);