类的加载,反射和注解详解


类的加载

概述

当程序运行时,会将磁盘中的.class文件加载到内存中,并创建Class对象(基于.class文件创建)
Class对象:存储的是.class文件中的内容(构造方法,成员变量,成员方法)

  • 构造方法:构造器对象Constructor对象
  • 成员变量:字段对象Field对象
  • 成员方法:方法对象Method对象

类加载器

作用

是Java运行时环境的一部分,负责加载字节码文件,即将磁盘上的某个class文件读取到内存并生成Class对象

分类

  • 启动类加载器(Bootstrap ClassLoader):加载核心类库
  • 扩展类加载器(Extension ClassLoader):加载扩展类库
  • 应用程序类加载器(Application ClassLoader):加载程序员自己定义的类

Snipaste_2024-04-16_16-11-32.png

获取类加载器的方式

public ClassLoader getClassLoader() //返回该类的类加载器,启动类加载器的对象为null

双亲委派机制

3种加载器的关系

  1. 自定义类加载器的父级加载器为扩展类加载器
  2. 扩展类加载器的父级类加载器是启动类加载器

加载器的结论:这种关系称为类加载器的双亲委派模型

工作机制

  1. 某个"类加载器"收到类加载的请求,它首先不会尝试自己去加载这个类,而是把请求交给父级类加载器
  2. 因此,所有的类加载的请求最终都会传送到顶层的"启动类"加载器中
  3. 如果"父级类加载器"无法加载这个类,如何子级类加载器再去加载

类加载器的应用

加载配置文件并生成字节输入流
InputStream getResourceAsStream(“关联配置文件”)
结合Properties对象使用
注意:如果配置文件在src目录下,直接输入配置文件的文件名(相对路径,相对的是src目录)
代码如下:

public class Demo2 {
    public static void main(String[] args) throws IOException {

        //类对象
        Class aClass = Demo2.class;
        //根据类对象获取类加载器对象
        ClassLoader classLoader = aClass.getClassLoader();
        //根据类加载器对象,获取输入流
        InputStream is = classLoader.getResourceAsStream("user.properties");
        //创建Properties类
        Properties prop = new Properties();
        //prop读取is
        prop.load(is);
        //根据prop获取配置文件中的内容
        String name = prop.getProperty("name");
        System.out.println(name);
        int age = Integer.parseInt(prop.getProperty("age"));
        System.out.println(age);
    }
}

反射

概述

是运行时获取类的字节码文件对象,任何可以解析类中的全部成分

  • 反射是针对Class对象进行操作的
  • 是一种类的解剖技术(.class文件中书写有:构造方法,成员变量,成员方法)
    • 反射就可以获取.class文件中的构造方法,成员变量,成员方法
    • 获取到Constructor进行创建对象
    • 获取到Field进行赋值取值
    • 获取到Method可以调用方法执行

关键

得到编译以后的Class对象

获取类对象

  1. Class cls = Class.forName(“类的全限定名”);

类的全限定名:com.mysql.jdbc.Driver
要使用:Driver类
导入包:com.mysql.jdbc.Driver
编写代码:Driver driver = new Driver(); // 要求Driver类必须存在(如果Driver类不存在,代码报错)
Class.forName(“com.mysql.jdbc.Driver”);//不要求Driver类必须存在(不存在也不会报错)

  1. Class cls = 类名.class;

当在方法区中创建了.class文件的Class对象后,就可以使用

  1. Class cls = 对象名.getClass();

在创建具体的对象后,就可以通过对象名来获取Class对象
Snipaste_2024-04-16_17-04-20.png

获取构造器对象

通过类对象来获取Constructor
Snipaste_2024-04-16_17-09-15.png
11.png
获取私有构造器要想进行创建对象,在创建对象之前使用暴力破解即可
:继承中,父类的私有内容是可以继承的,但是由于java语言有权限过滤检查,所以不允许权限外的内容;Class对象总存储的private构造器,由于java语言有权限过滤检查,所以不允许访问私有构造器,而暴力破解可以设置本次访问暂时取消权限检查

获取方法对象

通过类对象获取Method
Snipaste_2024-04-16_18-19-52.png
Snipaste_2024-04-16_18-32-18.png
静态方法填null

获取成员变量对象

通过类对象获取Field
Snipaste_2024-04-16_18-44-49.png
Snipaste_2024-04-16_18-45-26.png

作用

  1. 在运行时得到一个类的全部成分任何操作
  2. 可以破坏封装性(很突出)
  3. 更重要的用途是适合:做Java高级框架
  4. 基本上主流框架都会基于反射设计一些通用技术功能

注解

概述

Annotation,对代码的描述,作为代码形式表示出来
单独使用没有任何意义,通常会结合反射技术一起使用

作用

可以书写在类、接口、自定义注解、构造器、成员方法、成员变量、参数
被注解标注的内容,可以实现一些特殊的作用(具体的作用以实际开发中的需求为准)

自定义注解

就是自己做一个注解来使用

格式

public @interface 注解名称 {
public 属性类型 属性名() default 默认值;
}

属性类型

  1. 八种基本数据类型
  2. String,Class,注解类型,枚举类
  3. 以上类型的一维数组形式

特殊属性

  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写,@UserService(“userService”)
  • 但是如果有多个属性,且多个属性没有默认值,那么value名称不能省略

元注解

书写在自定义注解上的注解(JDK提供的)

常见的元注解

  • @Target:约束自定义注解只能在哪些地方使用
  • @Retention:声明注解的生命周期

Snipaste_2024-04-16_20-08-43.png

注解解析

概述

注解中的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容

方法

s.png

技巧

  1. 判断某个位置上是否存在自定义注解
  2. 存在,对自定义注解进行解析
  • 31
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Zeal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值