类加载机制与反射

目录

一、反射:Reflection

二、反射源头:java.lang.Class

1.Class类:

2.类的加载、连接、初始化:

类加载:

类的连接:

类的初始化:

类加载器:ClassLoader

Class的实例

如何获取Class的实例

Class的实例能干什么?

***通过反射调用类的方法、属性

三、反射的应用:

动态代理与AOP


一、反射:Reflection

反射机制允许程序在执行期借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

反射机制提供的功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 生成动态代理

反射相关的API

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造方法

 

二、反射源头:java.lang.Class

1.Class类:

特点:

  • Class本身也是一个类
  • Class对象只能有系统建立对象
  • 一个类在JVM中共只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个Class实例所生成
  • 通过Class可以完整地得到一个类中的完整结构

通过对象反射求出类名示例:



2.类的加载、连接、初始化:

当程序使用某个类,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来对该类进行初始化。如无意外,JVM会连续完成这三个步骤,所有有时也成为类加载或类初始化。 

类加载:

将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说,当程序使用任何类时,系统都会为之创建一个java.lang.Class对象。

系统中所有类实际上也是对象,他们都是java.lang.Class的实例

由类加载器完成的。

 

类的连接:

连接负责把类的二进制数据合并到JRE中,分为3阶段:

  • 验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
  • 准备:类准备阶段则负责为类的类变量分配内存,并设置默认初始化
  • 解析:将类的二进制数据中的符号引用替换成直接引用

 

类的初始化:

主要对类变量进行初始化。

 

类加载器:ClassLoader

将类的class文件读入内存,并为之创建一个java.lang.Class对象

 

Class的实例

每个类被加载之后,系统就会为改类生成一个对应的Class对象,通过改Class对象就可以访问到JVM中的这个类。

我们创建一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)。此.class文件加载到内存以后,就是一个运行时类,放在缓存区。那么这个运行时类本身就是一个Class的实例!

每个运行时类只加载一次

有了Class的实例以后,我们才可以进行如下操作:

  • *创建对应的运行时类的对象。
  • 获取对应的运行时类的完整解雇(属性、方法、构造器、内部类、父类、所在的包、异常、注解...)
  • *调用对应的运行时类指定的结构(属性、方法、构造器)
  • 反射的应用:动态代理

如何获取Class的实例

  1. 调用运行时类本身的.class属性
  2. 通过运行时类的对象获取
  3. 通过Class 的静态方法获取
  4. 通过类的加载器
@Test
    public void test4() throws ClassNotFoundException{
        // 1.调用运行时类本身的.class属性
        Class clazz = Person.class;
        System.out.println(clazz.getName());
        
        Class clazz2 = String .class;
        
        // 2. 通过运行时类的对象获取
        Person p = new Person();
        Class clazz3 = p.getClass();

        // 3.通过Class 的静态方法获取
        String className = "com.taiheyule.yinghe.Person";
        Class clazz4 = Class.forName(className);

        // 4.通过类的加载器(了解)
        String className1 = "com.taiheyule.yinghe.Person";
        ClassLoader classLoader = this.getClass().getClassLoader();
        Class clazz5 = classLoader.loadClass(className1);

    }

Class的实例能干什么?

创建运行时类的对象

调用Class对象的newInstance()

要求:

  • 类必须有一个无参的构造器。
  • 类的构造器访问权限足够。
 @Test
    public void test6() throws Exception{
        String className ="com.taiheyule.yinghe.Person";
        Class clazz = Class.forName(className);
        // 创建对应的运行时类的对象,newINnstance()调用的是运行时类的空参构造器,构造器的权限要足
        Object obj = clazz.newInstance();
        Person p = (Person)obj;
        System.out.println(p);
    }

 

获取运行时类的完整结构

运行时类的属性:

  

运行时类的方法:

***通过反射调用类的方法、属性

调用属性:

调用方法:

三、反射的应用:

动态代理与AOP

静态代理、动态代理

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值