文章目录
- 类的加载
- 概述
- 类加载器
- 作用
- 分类
- 获取类加载器的方式
- 双亲委派机制
- 3种加载器的关系
- 工作机制
- 类加载器的应用
- 反射
- 概述
- 关键
- 获取类对象
- 获取构造器对象
- 获取方法对象
- 获取成员变量对象
- 作用
- 注解
- 概述
- 作用
- 自定义注解
- 格式
- 属性类型
- 元注解
- 常见的元注解
- 注解解析
- 概述
- 方法
- 技巧
类的加载
概述
当程序运行时,会将磁盘中的.class文件加载到内存中,并创建Class对象(基于.class文件创建)
Class对象:存储的是.class文件中的内容(构造方法,成员变量,成员方法)
- 构造方法:构造器对象Constructor对象
- 成员变量:字段对象Field对象
- 成员方法:方法对象Method对象
类加载器
作用
是Java运行时环境的一部分,负责加载字节码文件,即将磁盘上的某个class文件读取到内存并生成Class对象
分类
- 启动类加载器(Bootstrap ClassLoader):加载核心类库
- 扩展类加载器(Extension ClassLoader):加载扩展类库
- 应用程序类加载器(Application ClassLoader):加载程序员自己定义的类
获取类加载器的方式
public ClassLoader getClassLoader() //返回该类的类加载器,启动类加载器的对象为null
双亲委派机制
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对象
获取类对象
- 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类必须存在(不存在也不会报错)
- Class cls = 类名.class;
当在方法区中创建了.class文件的Class对象后,就可以使用
- Class cls = 对象名.getClass();
在创建具体的对象后,就可以通过对象名来获取Class对象
获取构造器对象
通过类对象来获取Constructor
获取私有构造器要想进行创建对象,在创建对象之前使用暴力破解即可
注:继承中,父类的私有内容是可以继承的,但是由于java语言有权限过滤检查,所以不允许权限外的内容;Class对象总存储的private构造器,由于java语言有权限过滤检查,所以不允许访问私有构造器,而暴力破解可以设置本次访问暂时取消权限检查
获取方法对象
通过类对象获取Method
静态方法填null
获取成员变量对象
通过类对象获取Field
作用
- 在运行时得到一个类的全部成分任何操作
- 可以破坏封装性(很突出)
- 更重要的用途是适合:做Java高级框架
- 基本上主流框架都会基于反射设计一些通用技术功能
注解
概述
Annotation,对代码的描述,作为代码形式表示出来
单独使用没有任何意义,通常会结合反射技术一起使用
作用
可以书写在类、接口、自定义注解、构造器、成员方法、成员变量、参数
被注解标注的内容,可以实现一些特殊的作用(具体的作用以实际开发中的需求为准)
自定义注解
就是自己做一个注解来使用
格式
public @interface 注解名称 {
public 属性类型 属性名() default 默认值;
}
属性类型
- 八种基本数据类型
- String,Class,注解类型,枚举类
- 以上类型的一维数组形式
特殊属性:
- value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写,@UserService(“userService”)
- 但是如果有多个属性,且多个属性没有默认值,那么value名称不能省略
元注解
书写在自定义注解上的注解(JDK提供的)
常见的元注解
- @Target:约束自定义注解只能在哪些地方使用
- @Retention:声明注解的生命周期
注解解析
概述
注解中的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
方法
技巧
- 判断某个位置上是否存在自定义注解
- 存在,对自定义注解进行解析