notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • Java开发

    • My

    • Posts

    • Java SE

      • 黑马课程

        • 持有对象(集合)
        • 日志
        • Java I/O 系统
        • 多线程
        • 单元测试、反射与注解
          • 1. 单元测试
            • 1.1 单元测试概述
            • 1.2 单元测试快速入门
            • 1.3 单元测试常用注解
          • 2. 反射
            • 2.1 概述
            • 2.2 获取 Class 对象
            • 2.3 获取 Constructor 对象
            • 2.4 获取 Field 对象
            • 2.5 获取 Method 对象
            • 2.6 反射的作用 —— 绕过编译阶段为集合添加数据
            • 2.7 反射的作用 —— 通用框架的底层原理
          • 3. 注解
            • 3.1 概述
            • 3.2 自定义注解
            • 3.3 元注解
            • 3.4 注解解析
            • 3.5 注解的应用场景练习:JUnit
        • 权限修饰符与代码块
        • Java 代理机制
      • 专栏:Java 核心技术面试精讲

      • Effective Java

    • Java 并发编程

    • JVM

    • JDBC

    • Java Web

    • Spring 与 SpringMVC

    • Spring Boot

    • Spring Cloud

    • Spring Security

    • Netty

    • MyBatis

  • Python开发

  • Golang开发

  • Git

  • 软件设计与架构

  • 大数据与分布式系统

  • 区块链

  • Nginx

  • 开发
  • Java开发
  • Java SE
  • 黑马课程
yubin
2022-01-30
目录

单元测试、反射与注解

# 1. 单元测试

# 1.1 单元测试概述

单元测试就是针对最小的功能单元编写测试代码,Java 程序最小的功能单元是方法,因此,单元测试就是针对 Java 方法的测试,进而检查方法的正确性。

JUnit 是使用 Java 语言实现的单元测试框架,几乎所有的 IDE 工具都集成了 JUnit,这样我们就可以直接在 IDE 中编写并运行 JUnit 测试。

JUnit 优点:

  • 可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法
  • 可以生成全部方法的测试报告
  • 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试

# 1.2 单元测试快速入门

需求:使用单元测试进行业务方法预期结果、正确性测试的快速入门

过程:

  1. 将 JUnit 的 jar 包导入到项目中;
  2. 编写测试方法:该测试方法必须是公共的无参数无返回值的非静态方法;
  3. 在测试方法上使用 @Test注解:标注该方法是一个测试方法;
  4. 在测试方法中完成被测试方法的预期正确性测试(用 Assert 类);
  5. 选中测试方法,选择“JUnit运行” :红色失败,绿色成功。

进行预期的正确性测试:断言——Assert.assertEquals(...)。

# 1.3 单元测试常用注解

Junit 常用注解(Junit 4.xxxx版本):

注解 说明
@Test 测试方法
@Before 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。
@After 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeClass 用来静态修饰方法,该方法会在所有测试方法之前只执行一次。
@AfterClass 用来静态修饰方法,该方法会在所有测试方法之后只执行一次。
  • 开始执行的方法:初始化资源。
  • 执行完之后的方法:释放资源。

Junit 常用注解(Junit 5.xxxx版本):

注解 说明
@Test 测试方法
@BeforeEach 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。
@AfterEach 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeAll 用来静态修饰方法,该方法会在所有测试方法之前只执行一次。
@AfterAll 用来静态修饰方法,该方法会在所有测试方法之后只执行一次。

# 2. 反射

# 2.1 概述

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。

  • 在运行时,可以直接得到这个类的构造器对象:Constructor
  • 在运行时,可以直接得到这个类的成员变量对象:Field
  • 在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为 Java 语言的反射机制。

反射的核心思想和关键就是:得到编译以后的 class 文件对象

HelloWorld.java -> javac -> HelloWorld.class

Class c = HelloWorld.class;
1

# 2.2 获取 Class 对象

image-20220131150236109

三种方式:

  1. Class.forName("com.example.Student")
  2. Student.class
  3. s.getClass()

# 2.3 获取 Constructor 对象

方法 说明
Constructor<?>[] getConstructors() 返回所有构造器对象的数组(只能拿public的)
Constructor<?>[] getDeclaredConstructors() 返回所有构造器对象的数组,存在就能拿到
Constructor<T> getConstructor(Class<?>... parameterTypes) 返回单个构造器对象(只能拿public的)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回单个构造器对象,存在就能拿到

获取构造器的作用依然是初始化一个对象。Constructor 类中用于创建对象的方法:

符号 说明
T newInstance(Object... initargs) 根据指定的构造器创建对象
public void setAccessible(boolean flag) 设置为true,表示取消访问检查,进行暴力反射,从而可以拿到私有的构造器来创建对象,这个方式破坏了封装性。

# 2.4 获取 Field 对象

方法 说明
Field[] getFields() 返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields() 返回所有成员变量对象的数组,存在就能拿到
Field getField(String name) 返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name) 返回单个成员变量对象,存在就能拿到

获取成员变量可以在某个对象中取值、赋值,Field 类中用于取值、赋值的方法:

符号 说明
void set(Object obj, Object value): 赋值
Object get(Object obj) 获取值。

如果成员是非 public 的,那可以用 setAccessible 打开权限。

# 2.5 获取 Method 对象

方法 说明
Method[] getMethods() 返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class<?>... parameterTypes) 返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回单个成员方法对象,存在就能拿到

l获取成员方法后可以在某个对象中进行执行此方法,Method 类中用于触发执行的方法:

符号 说明
Object invoke(Object obj, Object... args) 运行方法。参数一:用obj对象调用该方法; 参数二:调用方法的传递的参数(如果没有就不写);返回值:方法的返回值(如果没有就不写)

如果方法是非 public 的,那可以用 setAccessible 打开权限。

# 2.6 反射的作用 —— 绕过编译阶段为集合添加数据

反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素。因为泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成 Class 文件进入运行阶段的时候,其真实类型都是原生 ArrayList 了,泛型相当于被擦除了。反射是作用在运行时的技术,此时已经不存在泛型了。

# 2.7 反射的作用 —— 通用框架的底层原理

需求:给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文件中去。比如:

image-20220131154633699

分析:

  1. 定义一个方法,可以接收任意类的对象;
  2. 使用反射获取对象的Class类对象,然后获取全部成员变量信息;
  3. 遍历成员变量信息,然后提取本成员变量在对象中的具体值;
  4. 存入成员变量名称和值到文件中去即可。

基本上主流框架都会基于反射设计一些通用技术功能。

# 3. 注解

# 3.1 概述

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。类、构造器、方法、成员变量、参数等都可以被注解进行标注。

注解作用:对 Java 中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。

例如:JUnit 框架中,标记了注解 @Test 的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。

# 3.2 自定义注解

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

public @interface 注解名称 {
    public 属性类型 属性名() default 默认值;
}
1
2
3
  • Java 支持的数据类型基本上都支持

特殊属性——value 属性:如果只有一个 value 属性的情况下,使用 value 属性的时候可以省略 value 名称不写,但是如果有多个属性, 且多个属性没有默认值,那么value名称是不能省略的。

# 3.3 元注解

元注解:它也是一个注解,这个注解用来注解其他注解,即放在注解头上的注解。

常见的元注解:

# 1)@Target

约束自定义注解只能在哪些地方使用。它可使用的值定义在 ElementType 枚举类中,常用值如下:

  • TYPE,类,接口
  • FIELD, 成员变量
  • METHOD, 成员方法
  • PARAMETER, 方法参数
  • CONSTRUCTOR, 构造器
  • LOCAL_VARIABLE, 局部变量

# 2)@Retention

申明注解的存活范围。它可使用的值定义在 RetentionPolicy 枚举类中,常用值如下:

  • SOURCE: 注解只作用在源码阶段,被编译器丢弃,生成的字节码文件中不存在
  • CLASS: 注解作用在源码阶段、字节码文件阶段,被 VM 丢弃,运行阶段不存在,默认值.
  • RUNTIME:注解作用在源码阶段、字节码文件阶段和运行阶段(开发常用),可以通过反射机制读取注解的信息。

# 3.4 注解解析

注解的解析就是判断是否存在注解,存在注解就解析出内容。

与注解解析相关的接口:

  • Annotation: 注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法
方法 说明
Annotation[] getDeclaredAnnotations() 获得当前对象上使用的所有注解,返回注解数组。
T getDeclaredAnnotation(Class<T> annotationClass) 根据注解类型获得对应注解对象
boolean isAnnotationPresent(Class<Annotation> annotationClass) 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

所有的类成分 Class, Method , Field , Constructor,都实现了 AnnotatedElement 接口,他们都拥有解析注解的能力

解析注解的技巧:注解在哪个成分上,我们就先拿哪个成分对象

  • 比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
  • 比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
  • 比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解

# 3.5 注解的应用场景练习:JUnit

需求:定义若干个方法,只要加了 MyTest 注解,就可以在启动时被触发执行

分析

  1. 定义一个自定义注解 MyTest,只能注解方法,存活范围是一直都在。
  2. 定义若干个方法,只要有 @MyTest 注解的方法就能在启动时被触发执行,没有这个注解的方法不能执行
编辑 (opens new window)
上次更新: 2023/06/17, 10:36:05
多线程
权限修饰符与代码块

← 多线程 权限修饰符与代码块→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×