- 初始反射
- 反射的基本操作
- 反射安全性问题
反射是指在Java运行状态
中:
-
给定一个类对象(Class对象),通过反射获取这个类对象(Class对象)的所有成员结构;
-
给定一个具体的对象,能够动态地调用它的方法及对任意属性值进行获取和赋值;
-
这种动态获取类的内容、创建对象、以及动态调用对象方法及操作属性的机制,就叫做Java的反射机制。
优点
-
增加程序的灵活性,避免将固有的逻辑程序写死到代码里
-
代码简洁,可读性强,可提高代码的复用率
缺点
-
相较直接调用在创建对象比较多的情景下反射性能下降
-
内部暴露和安全隐患(破坏单例)
反射性能慢原因
-
寻找类Class字节码的过程,比如通过ClassName找到对应的字节码Class,然后进行加载、解析,也会比较慢,而new的方式则无需寻找,因为在Linking的解析阶段已经将符号引用转为了直接引用
-
安全管理机制的权限验证等等
-
若需要调用native方法调用时JNI接口的使用
-
入参校验
获取Class对象的四种方式:
- 通过ClassLoader对象的loadClass()方法。
- 使用类名.class。
- 使用Class.forName()。
- 通过对象调用getClass()方法
基本信息操作
// 获取类修饰符
int modifiers = clazz.getModifiers();
// 获取类包名
Package aPackage = clazz.getPackage();
// 获取类的全路径名称
String fullClassName = clazz.getName();
// 获取类的简单名称
String simpleName = clazz.getSimpleName();
// 获取类加载器
ClassLoader classLoader = clazz.getClassLoader();
// 获取类实现的接口列表
Class[] interfaces = clazz.getInterfaces();
// 获取类的父类
Class superclass = clazz.getSuperclass();
// 获取类的注解信息
Annotation[] annotations = clazz.getAnnotations();
类的属性操作
Object instance = clazz.newInstance();
// 获取类中所有的共有字段 包含继承的字段
Field[] fields = clazz.getFields();
// 获取类中定义的字段 内部
Field[] declaredFields = clazz.getDeclaredFields();
// 获取指定名称的类中定义的字段
Field nameField = clazz.getDeclaredField("name");
// 获取字段的修饰符
int fieldModifiers = nameField.getModifiers();
// 指定字段强制访问
nameField.setAccessible(true);
// 修改字段你的值
nameField.set(instance, "samuel");
// 静态字段赋值
nameField.set(null, "静态字段赋值");
类的方法操作
// 静态字段赋值
Method[] methods = clazz.getMethods();
// 静态字段赋值
Method[] declaredMethods = clazz.getDeclaredMethods();
// 获取类中指定名称和参数的公有方法
Method say = clazz.getMethod("say", String.class);
// 获取类中指定名称和参数的公有方法
Method say1 = clazz.getDeclaredMethod("say");
// 获取方法的修饰符
int methodModifiers = say.getModifiers();
// 指定对象进行成员方法的调用
say.invoke(instance, "samuel666");
// 指定方法的强制执行
say.setAccessible(true);
// 静态方法调用
say.invoke(null);
类的构造器操作
//获取类中所有的公有构造器
Constructor[] cons = clazz.getConstructors();
//获取类中所有的构造器
Constructor[] cons1 = clazz.getDeclaredConstructors();
//获取类中无参的构造器
Constructor conNoParam= clazz.getDeclaredConstructor();
//获取类中有参构造
Constructor con= clazz.getDeclaredConstructor(String.class,String.class);
//获取构造器的修饰符
int modifers = con.getModifiers();
//构造器实例对象
conNoParam.newInstance();
//指定方法的强制访问
con.setAccessible(true);
//有参构造调用
con.newInstance("abc","bbb");
//class直接调用默认无参构造
Person.class.newInstance();