1、类加载器
1.1类加载器作用
负责将.class文件(存储的物理文件)加载在到内存中。
1.2类加载的过程
类加载时机
- 创建类的实例(对象)
- 调用类的类方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
类加载过程
i. 加载
- 通过包名 + 类名,获取这个类,准备用流进行传输
- 在这个类加载到内存中
- 加载完毕创建一个class对象
ii. 链接
验证--确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安 全 (文件中的信息是否符合虚拟机规范有没有安全隐患)
准备--负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值 (初始化静态变量)
解析--将类的二进制数据流中的符号引用替换为直接引用 (本类中如果用到了其他类,此时就需要找到对应的类)
iii. 初始化--根据程序员通过程序制定的主观计划去初始化类变量和其他资源 (静态变量赋值以及初始化其他资源)
当一个类被使用的时候,才会加载到内存---类加载的过程: 加载、验证、准备、解析、初始化。
1.3类加载的分类
分类
- Bootstrap class loader:虚拟机的内置类加载器,通常表示为null ,并且没有父null
- Platform class loader:平台类加载器,负责加载JDK中一些特殊的模块
- System class loader:系统类加载器,负责加载用户类路径上所指定的类库
类加载器的继承关系---System的父加载器为Platform Platform的父加载器为Bootstrap。
1.4 ClassLoader 中的两个方法
方法名 | 说明 |
public static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
public InputStream getResourceAsStream(String name) | 加载某一个资源文件 |
2.反射
2.1 反射的概述
反射机制---是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意属性和方法; 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
2.2获取Class类对象的三种方式
三种方式分类
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
获取里面的构造方法对象
getConstructor (Class... parameterTypes) getDeclaredConstructor (Class... parameterTypes)
如果是public的,直接创建对象
newInstance(Object... initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射
2.3反射获取成员变量
反射和配置文件优化
Class类获取成员变量对象的方法
方法名 | 说明 |
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
2.4 Field类用于给成员变量赋值的方法
方法名 | 说明 |
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
2.5 反射获取成员方法
方法名 | 说明 |
Method[] getMethods() | 返回所有公共成员方法对象的数组, 包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组, 不包括继承的 |
Method getMethod(String name, Class... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class... parameterTypes) | 返回单个成员方法对象 |
2.6 Method类用于执行方法
方法名 | 说明 |
Object invoke(Object obj, Object... args) | 运行方法 |
2.7 反射机制常见的使用场景
- 动态创建对象:在运行时,根据类名字符串动态创建对象实例。
- 访问私有成员:通过反射可以访问类中私有的字段和方法,尽管这通常不被推荐,因为它违反了封装原则。
- 获取类的结构信息:获取类的所有属性和方法信息,包括私有的属性和方法。
- 动态调用方法:在运行时调用对象的方法,特别是当方法名是动态决定的时候。
- 设计灵活的代码:编写可以在运行时适应不同类型对象的代码,提高代码的通用性和灵活性。
- 实现工厂模式:使用反射来实现基于类的名称来创建对象的简单工厂模式。
- 实现依赖注入:许多现代Java框架(如Spring)使用反射来自动装配依赖。
- 创建代理:动态代理模式利用反射来创建代理类,以拦截和处理方法调用。
- 注解处理:Java的注解处理器在编译时使用反射读取注解信息。
- 实现单元测试:在测试框架中,反射可以用于测试私有方法或模拟对象。
- 实现ORM框架:对象关系映射(ORM)框架,如Hibernate,使用反射来自动映射数据库表到Java对象。
- 自定义类加载器:通过反射实现自定义类加载器,以动态加载字节码。
- 序列化和反序列化:某些序列化机制可能使用反射来读取对象的状态。
- 实现事件监听机制:事件监听器模式可能会使用反射来动态地注册和处理事件。
- 动态配置:应用程序可以根据配置文件动态地加载和使用不同的类。
3.注解
3.1概述
对我们的程序进行标注和解释
注解和注释的区别
- 注释: 给程序员看的
- 注解: 给编译器看的
使用注解进行配置配置的优势,代码更加简洁,方便。
3.2 自定义注解
格式:
public @interface 注解名称 { public 属性类型 属性名() default 默认值 ;}
属性类型
- 基本数据类型
- String
- Class
- 注解
- 枚举
- 以上类型的一维数组
3.3 元注解
元注解就是描述注解的注解;
元注解介绍