一、注解
学前疑惑:
- 干啥用的?
- 类似于注释,给编译器看的?看的什么东西呢。加载的时候会有什么不同?
- 虽然语法上有点像 python 的装饰器,但是作用似乎不一样
1.1 什么是注解
- 可以对程序作出解释(类似于注释,是给编译器看的)
- 可以被其他程序(如编译器等)读取
1.2 元注解
用于注解其他注解的注解,即对注解进行一些说明。
共有4个 —— @Target, @Retention, @Document, @Inherited
@Target
- 描述注解的使用范围,作用于方法、类等
@Retention
- 表示注解在什么地方还有效
- SOURCE < CLASS < RUNTIME
- 默认用 RUNTIME
@Document
- 表示是否将注解生成在 javadoc 中
@Inherited
- 说明子类可以继承父类注解
1.3 自定义注解
1 | (RetentionPolicy.RUNTIME) |
- 使用
@interface
声明注解 - 其中的每个方法,实际为一个配置参数
- 如果只有一个参数成员,一般参数名为
value
- 默认值用
default
二、反射机制
学前疑惑:
- 什么是反射,有什么作用?
- 为什么不直接new出来对象调用呢?
2.1 基础概念
2.1.1 相关知识
静态语言 & 动态语言:
动态语言
- 【在运行时检查】
- 在运行时可以改变结构的语言,即变量、函数等可以在运行时改变类型(JS、Python 等)
静态语言
- 【在编译期检查】
- 相对应的,不能改变类型,声明了类型就不许改变(Java、C++ 等)
强类型 & 弱类型:
- 强类型
- 【不会隐式做语言类型转换】
- 弱类型
- 【做隐式类型转换】
2.1.2 反射概念
- 反射机制允许程序在执行期间获取类本身的各种定义,如属性、方法等
- 与new对象的方式相反:
- new 对象:import 包 -> new 对象 -> 取得实例化对象
- 反射:实例化对象 -> getCalss() 方法 -> 得到完整的”包类“名称
- 由于和new对象的过程相反,所以有「反射」的叫法
2.1.3 反射的作用
- 在运行时判断对象所属的类
- 在运行时构造对象
- 在运行时调用对象的成员变量和方法
- 。。。
2.1.4 反射优点和缺点
优点:
- 动态创建对象和编译
缺点:
- 性能低
- 反射类似于解释操作,告诉JVM我需要什么,然后JVM来做,会比我们直接操作要慢
2.2 反射
2.2.1 获取反射对象
- 一个类在内存中只有一个Class对象
- 一个类被加载后,整个类结构都会封装在 Class 对象中
1 | Class c1 = Class.forName("com.shuofxz.reflection.User"); |
2.2.2 Class
是什么
- Class 本身也是一个类
- Class 对象只能由系统(JVM)创建
特征
- 一个类只会在 JVM 中有一个 Class 实例
- 每个类的实例都知道自己是由哪个 Class 实例生成
用处
- 通过 Class 实例可以获得一个类中所有被加载的结构
- 通过 Class 可以动态加载运行类(即反射)
获取 Class 类的实例
1 | // 1) 从类获得 |
- 类加载 与 ClassLoader
- 详细请看 JVM 篇
- 方法区:从 .class 文件中加载类数据到方法区(每个类数据包括静态变量、静态方法、常量池、代码等)
- 堆:以方法区类数据作为模板,生成出类对象;再由「类对象」生成出「对象」
- 栈:程序执行,按照代码赋值对象,执行方法
三、注解与反射
注解可以通过反射机制起作用
- 获取到一个类实例后,通过反射的方式拿到所写的注解信息
- 再通过类本身信息 + 注解的信息 完成一些操作
- 如操作数据库的时候,会给类属性对应一个数据库列的名字,就可以用注解来对应
- 相当于一个语法糖?
- 将一些本该由更多代码实现的对应信息,通过注解简单的方式实现了
作用
简化代码
结偶
- 比方原来需要通过继承或者实现方式获得的属性和方法,通过注解方式结偶