java学习笔记(二十三)- 反射
java学习笔记(二十三)- 反射
执笔反射机制
- 反射机制(Java Refection)允许程序在执行期借助与Refection API取得任何类的内部信息(如:成员变量、构造器、成员方法等),并能直接操作对象的属性及方法
1、应用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
相关的类
1 | (1)java.lang.Class//代表一个类,Class对象表示某个类加载后再堆中的对象 |
3、优点和缺点
优点:
- 可以动态的创建和使用对象(框架底层核心),使用灵活
缺点:
- 使用反射基本是解释执行,对执行速度有影响
调用优化
关闭访问检查:
1
.setAccessble(true)//点前面加Method、Filed、Constructor对象
开启访问检查:
1
.setAccessble(false)//点前面加Method、Filed、Constructor对象,默认开启访问检查
Class类
基本介绍
Class类也是类,继承了Object类
Class类对象不是new出来的,而是系统创建的
对于某个类的Class对象,在内存中只有一份,因为类只加载一次
通过Class对象可以得到一个类的完整结构
Class对象存放在堆中
类的字节码二进制数据,是放在方法区(或者称为类的元数据(包括方法代码、变量名、方法名、访问权限等)
应用
1 | public class Class02 { |
获取Class对象
Class.forName
- 前提:已知一个类的全类名,且该类在类的路径下,可通过Class类的静态方法forName()获取
- 应用场景:多用于配置文件,读取类全路径,加载类
1 | //1. Class.forName |
类名.Class
- 前提:已知具体的类,通过类的Class获取,该方式最为安全可靠,程序性能最高
- 应用场景:多用于参数传递
1 | //2. 类名.class 多用于参数从传递 |
对象.getClass()
- 前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象
- 应用场景:通过创建好的对象,获取Class对象
1 | //3. 对象.getClass() 已知对象实例 |
通过类加载器[4种]
1 | //ClassLoader cl = 对象.getClass.getClassLoader(); |
基本数据类型
1 | //Class cls = 基本数据类型.class |
基本数据类型的包装类
1 | //Class cls = 包装类.TYPE |
拥有Class对象的类型
1 | Class<String> cls = String.class;//外部类,成员内部类,静态内部类,局部内部类,匿名内部类 |
类加载
静态加载
- 编译时加载相关的类,如果没有就报错,依赖性强
- 场景:
- 当创建对象时(new)
- 当子类被夹在时,父类也加载
- 调用类中的静态成员
动态加载
- 运行时加载需要的类,如果不运行时不用该类,即使不存在该类也不报错,降低了依赖性
- 场景:反射
类加载过程
加载阶段
- 将字节码从不同的数据源(class文件、jar包、网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象
连接阶段
验证
- 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
- 包括:问价格式验证(是否以魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证
- 缩短虚拟机类加载时间:-Xverify:none 参数来关闭大部分的类验证措施
准备
- 对静态变量分配内存并初始化(对应数据类型的默认初始值:如0、0L、null、false等),这些变量所使用的的内存都将在方法区中进行分配
解析
- 虚拟机将常量池内的符号引用替换为直接引用的过程
初始化(initialization)
- 到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行
(0)方法的过程 ()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并 - 虚拟机会保证一个类的
()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的 ()方法,其他线程都需要阻塞等待,直到活动线程执行 ()方法完毕
反射获取类结构信息
java.lang.Class类
1 |
|
java.lang.reflect.Field类
1 | getModifiers//以int形式返回修饰符 |
1 | Class<?> personCls = Class.forName("com.hzy.study.reflection.Person"); |
java.lang.reflect.Method类
1 | getModifiers//以int形式返回修饰符 |
1 | //6. getDeclaredMethods 获取本类中所有的方法 |
java.lang.reflect.Constructor类
1 | getModifiers//以int形式返回修饰符 |
1 | //8. getDeclaredConstructors 获取本类所有的构造器 |
反射创建对象
通过类中public修饰的无参构造器
1 | //1. 先获取到User类的Class对象 |
通过类中public修饰的有参构造器
1 | //3. 通过public 的有参构造器创建实例 |
通过非public修饰的有参构造器
1 | //4. 通过非public 的有参构造器创建实例 |
反射访问类中成员
访问属性
1 | //根据属性名获取Field对象 |
1 | //1. 获取Student 对应的Class对象 |
访问方法
1 | //根据方法名和参数列表获取Method方法对象: |
1 | //1. 获取Boos的Class对象 |
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果