反射

反射

image-20211001155347084

反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等)并能操作对象的属性及方法。反射在设计模式和框架底层都会遇到。

加载完类后,在堆中就产生了一个Class对象,这个对象包含了类的完整结构信息,通过这个对象得到类的结构。这个Class对象就像一面镜子一样,透过镜子可以看到类的结构。

反射的优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响。

优化:

Method,Constructor和Field对象都有setAccessible方法,作用是启动和禁用访问安全检查的开关。参数为true,表示访问的对象在使用时取消访问检查,提高反射效率,参数为false,表示反射的对象接受访问检查。

Class类

  1. Class也是类,继承Object类
  2. Class类不是new出来的,而是系统创建的
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次(同步机制)
  4. 每个类的实例都会记得自己是由哪个Class实例所生成
  5. 通过Class类对象可以完整的得到一个类的完整结构
  6. Class对象是存放在堆里的
  7. 类的字节码二进制数据,是存放在方法区里的,有的地方称为类的元数据

类加载

反射机制是Java实现动态语言的关键,也就是通过反射实现类的动态加载。

1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强。

2.动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在也不报错,降低了依赖性。

类加载的时机

  1. 当创建对象时:new
  2. 当子类被加载时
  3. 调用类中的静态成员时
  4. 通过反射

加载阶段:

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件,也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个该类的java.lang.Class对象

连接阶段-验证

  1. 目的是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
  2. 包括文件格式验证、元数据验证、字节码验证、符号引用验证

连接阶段-准备

  1. JVM会在这个阶段对静态变量,分配内存,并默认初始化(对应数据类型初始化默认初始值),这些变量所使用的内存都会在方法区中,进行分配。
class A{
	int n1=10;
    static int n2=20;
    static final n3=30;
    //n1是实例属性,不是静态变量,因此在准备阶段,是不会分配内存的,
    //n2是静态变量,会再此阶段分配内存,会进行默认初始化 n2=0,而不是20
    //n3是静态常量 与静态变量不一样 一旦赋值 就不变
}

连接阶段-解析

虚拟机将常量池中的符号引用转换为直接引用的过程

初始化

  1. 到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行方法的过程
  2. 方法是由编译器按语句在源文件中出现的顺序,依次自动收集的所有静态变量的赋值动作和静态代码块的语句进行合并。
  3. 虚拟机会保证一个类的方法在多线程环境中,被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程,去执行这个类的方法,其他线程都要阻塞。

image

API

getModifiers()返回以int形式表示的修饰符

默认修饰符是0,public是1,private是2,protect是4,static是8,final是16,

爆破:setAccessible

对象/构造器/字段.setAccessible(true) 可以访问私有构造器 方法 属性

静态属性 反射访问时,字段/方法.set(对象,值),静态属性访问时 对象可以写作null

posted @ 2021-11-30 23:24  依然学不会  阅读(25)  评论(0)    收藏  举报