【JAVA】单元测试、反射、注解、动态代理

1 单元测试

Junit常用注解(4.几版本)

@Test

测试方法

@Before

用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。

@After

用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。

@BeforeClass

用来静态修饰方法,该方法会在所有测试方法之前只执行一次。

@AfterClass

用来静态修饰方法,该方法会在所有测试方法之后只执行一次

Junit常用注解(5.几版本)

@Test

测试方法

@BeforeEach

用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。

@AfterEach

用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。

@BeforeAll

用来静态修饰方法,该方法会在所有测试方法之前只执行一次。

@AfterAll

用来静态修饰方法,该方法会在所有测试方法之后只执行一次

2 反射

反射是在运行时获取类的字节码文件对象,然后可以解析类中的全部成分

  • 反射的核心思想和关键:得到编译之后的class文件对象
  • 在运行时,可以直接得到这个类的构造器对象Constructor,类的成员变量对象Field,类的成员方法对象Method

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

反射的关键:

反射的第一步都是先获取Class类对象

// HelloWorld.java -> javac -> HelloWorld.class
// 方式一:类名.class
Class c= HelloWorld.class;
// 方式二:Class.forName("全类名")
Class c2 = Class.forName("包名.类名");
// 方式三:对象.getClass();
HelloWorld h = new HelloWorld();
Class c3 = h.getClass();
// 获取类的全名,即包名.类名
String name = Class.forName("包名.类名").getName();
// 只获取类名
String name = Class.forName("包名.类名").getSimpleName();

获取类对象后,我们可以类对象中获取类的成分对象

获取构造器

方法说明

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,表示取消访问检查,进行暴力反射

非public的构造器,反射可以破坏其封装性,私有也可以执行

获取成员变量

作用:在某个对象中取值、赋值

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)

获取值。

获取方法对象

作用:在某个对象中进行执行此方法

Method[] getMethods​()

返回所有成员方法对象的数组(只能拿public的)

Method[] getDeclaredMethods​()

返回所有成员方法对象的数组,存在就能拿到

Method getMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象(只能拿public的)

Method getDeclaredMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象,存在就能拿到

Method类中用于触发执行的方法

Object invoke​(Object obj, Object... args)

运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

反射的作用

绕过编译阶段为集合添加数据

反射是在运行时的技术,此时集合的泛型将不能产生约束了,此时可以为集合存入其它任意类型的元素

ArrayList<Integer> lists = new ArrayList<>();
list.add(100);
// list.add(“ABC"); // 报错
list.add(99);
// 但是下面方法可以添加字符串
Class l = lists.getClass();
Method add = l.getDeclaredMethod("add", Object.class);
add.invoke(lists, "ABC");

反射的作用:

  • 可以在运行时得到一个类的全部成分
  • 可以破坏封装性
  • 破坏泛型的约束性
  • 做Java高级框架

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

3 注解

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

自定义注解

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

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

元注解

注解的注解,放在注解上的注解

@Target:约束自定义注解只能在哪些地方使用

@Retention:申明注解的生命周期

@Target可使用的值定义在ElementType枚举类中,常用值如下

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

@Retention可使用的值定义在RetentionPolicy枚举类中,常用值如下

  • SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS:  注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

注解解析

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

  • Annotation:注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法

Annotation[]    getDeclaredAnnotations()

获得当前对象上使用的所有注解,返回注解数组。

T getDeclaredAnnotation(Class<T> annotationClass)

根据注解类型获得对应注解对象

boolean isAnnotationPresent(Class<Annotation> annotationClass)

判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

4 动态代理

代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理

关键步骤

必须有接口,实现类要实现接口(代理通常是基于接口实现)

创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象

优点

  • 非常灵活,支持任意接口类型的实现类对象做代理,也可以直接为本身做代理
  • 可以为被代理对象的所有方法做代理
  • 可以在不改变方法源码的情况下,实现对方法功能的增强
  • 不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率
// 返回是代理对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
// loader 是定义代理类的类加载器
// interfaces 代理类要实现的接口列表
// h 代理对象的核心处理逻辑
public class ProxyUtil {
    public static <T> T getProxy(T obj) {
        // 返回一个代理对象,给别人使用。
        // Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
        // 参数一:类加载器,负责加载代理类的
        // 参数二:需要被代理的方法在哪些接口中。
        // 参数三:代理对象的核心处理逻辑
        return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 核心处理逻辑
                        // proxy  代理对象:一般不需要理会。
                        // method 代表正在被代理的方法对象。
                        // args  被代理方法的参数值。
                        // 1、记录开始时间
                        long startTime = System.currentTimeMillis();
                        // 2、触发真正的业务对象的方法执行。
                        Object result = method.invoke(obj, args);
                        // 3、记录结束时间,统计耗时
                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName() + "方法耗时:" + (endTime - startTime) / 1000.0 + "s!");
                        return result; // 4、返回结果。
                    }
                });
    }
}
/**
    动态代理需要接口配合。
 */
public interface UserService {
    String login(String loginName, String passWord);
    void selectUsers();
    void deleteUsers();
}
// 创建业务对象
UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
// 调用方法
String time = userService.login("aaa", "1111")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/87049.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django REST framework实现api接口

drf 是Django REST framework的简称&#xff0c;drf 是基于django的一个api 接口实现框架&#xff0c;REST是接口设计的一种风格。 一、 安装drf pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install …

Mongodb两种启动方法

一、命令行启动 1.修改存放数据库的位置 说明&#xff1a;E:\data\mongodb&#xff1b;我在E盘创建的文件夹mongodb mongod --dbpathE:\data\mongodb 2.成功启动 说明&#xff1a;默认端口27017&#xff0c;代表已经启动成功 &#xff0c;并在mongodb自动创建文件 二、配置项…

JFrog Artifactory介绍

JFrog Artifactory 1. 简介2. 安装3. 使用说明3.1 界面展示3.2 仓库搭建流程&#xff08;本地库&#xff09;3.3 普通用户界面展示3.4 上传制品&#xff0c;可单传或多传3.5 下载制品3.6 支持搜索3.7 单个制品复制移动删除3.8 用户管理3.9 存储信息3.10 基本设置 4. 前期调研被…

什么是软件压力测试?软件压力测试工具和流程有哪些?

软件压力测试 一、含义&#xff1a;软件压力测试是一种测试应用程序性能的方法&#xff0c;通过模拟大量用户并发访问&#xff0c;测试应用程序在压力情况下的表现和响应能力。软件压力测试的目的是发现系统潜在的问题&#xff0c;如内存泄漏、线程锁、资源泄漏等&#xff0c;…

心理与神经生物工程交叉学科国际论坛—暨第17届复合医学工程国际会议(CME2023)

心理与神经生物工程交叉学科国际论坛—暨第17届复合医学工程国际会议&#xff08;CME2023&#xff09; International Forum on the Intersection of Psychology and Neuromedical Engineering -17th International Conference on Complex Medical Engineering (CME2023) 心…

IoT DC3 是一个基于 Spring Cloud 的开源的、分布式的物联网(IoT)平台本地部署步骤

dc3 windows 本地搭建步骤&#xff1a; ​​ 必要软件环境 进入原网页# 务必保证至少需要给 docker 分配&#xff1a;1 核 CPU 以及 4G 以上的运行内存&#xff01; JDK : 推荐使用 Oracle JDK 1.8 或者 OpenJDK8&#xff0c;理论来说其他版本也行&#xff1b; Maven : 推荐…

solidity0.8.0的应用案例10:可升级合约

这个案例是代理合约的实际操作&#xff0c;代理合约实现了逻辑和数据的分离&#xff0c;就可以实现在生产环境中&#xff0c;轻松升级合约&#xff0c;这就是一个如何实际升级合约的案例。 实现一个简单的可升级合约&#xff0c;它包含3个合约&#xff1a;代理合约&#xff0c;…

聚观早报|2023戴尔科技峰会助力创新;小米汽车电池供应商敲定

【聚观365】8月23日消息 2023戴尔科技峰会助力企业创新 小米汽车电池供应商敲定中创新航和宁德时代 iPhone15预计有6种配色 王小川卸任自动驾驶企业禾多科技董事 特斯拉动力总成副总裁宣布离职 2023戴尔科技峰会助力企业创新 近日“新生万物 数实新格局 —— 2023戴尔科技…

记录protocol buffers Mac安装

使用brew安装最新的protobuf 在Mac 上安装&#xff0c;使用brew 可以安装最新的protobuf。这个也比较简单&#xff0c;简单说一下。 首先先检查一下是否安装了brew。如果没有安装brew的话&#xff0c;请先安装brew.可以通过brew --version来检查 使用brew install protobuf 来…

【Modbus通信实验三】数据切片问题

在做两个串口相互通信的实验中&#xff0c;当发送频率快一点时偶尔会遇到以下情景&#xff0c;即一次send中把原数据拆成两份发送&#xff0c;就会导致CRC校验错误。下图中6字节数据拆成42是把SetRThreshold()阈值设为2&#xff0c;当设为1的情况下则会拆成51。 一开始以为是缓…

流弊的docker

docker就是隔离式运行软件组&#xff08;多个软件&#xff09;&#xff0c;docker分为dockerfile文件&#xff0c;images 镜像&#xff0c;容器&#xff0c;本地仓库&#xff0c;远程仓库。 ckerFile文件&#xff0c;可以获得images镜像 运行镜像获得容器 || 容器提交获得镜像…

二叉树---前,中,后序遍历做题技巧(前,中,后,层次,线索二叉树)

1.由二叉树求前&#xff0c;中&#xff0c;后序遍历 前序:根左右&#xff08;每一个小方块都遵循&#xff09; 得到&#xff1a;A,B,D,H,E,I,C,F,G 中序&#xff1a;左根右&#xff08;每一个小方块都遵循&#xff09; 得到&#xff1a;H,D,B,I,E,A,F,C,G 后序&#xff1a;左右…

QCC_BES 音频重采样算法实现

+V hezkz17进数字音频系统研究开发交流答疑群(课题组) 这段代码是一个用于将音频数据进行立体声重采样的函数。以下是对代码的解读: 函数接受以下参数: pcm_buf:16位有符号整型的音频缓冲区,存储了输入的音频数据。pcm_len:音频缓冲区的长度。mic1:16位有符号整型的音频…

本地生活服务平台加盟哪家公司好?

本地生活的竞争从年初的火热到现在&#xff0c;已经进入了下半场&#xff0c;随着优胜劣汰的筛选&#xff0c;那么直到现在&#xff0c;想做本地生活服务平台加盟&#xff0c;哪家公司比较好呢&#xff0c;应该如何选择呢&#xff1f; 首先我们得弄懂&#xff0c;我们加盟本地…

在线图片怎么转换成PDF?在线图片转换成PDF步骤介绍

文件格式要转化不知道怎么办?想要网上下载文件格式转换软件&#xff0c;但是却不知道下载哪个好?今天小编小编就给大家分享一下靠谱的小圆象PDF转换器工具&#xff0c;想知道这款软件好不好用?在线图片怎么转换成PDF?那就进来看看吧。 在线图片怎么转换成PDF 小圆象PDF转换…

科技资讯|荷兰电动自行车丢失将被拒保,苹果Find My可以减少丢失

荷兰最大的自行车协会荷兰皇家旅游俱乐部宣布&#xff0c;将不再为胖胎电动自行车提供保险&#xff0c;因为这种自行车的被盗风险极高。 随着电动自行车的销量飙升&#xff0c;胖胎也变得更受欢迎。但问题是&#xff0c;胖胎电动自行车也成为了自行车盗窃者的首选目标。ANWB …

设计模式之迭代器模式(Iterator)的C++实现

1、迭代器模式的提出 在软件开发过程中&#xff0c;操作的集合对象内部结构常常变化&#xff0c;在访问这些对象元素的同时&#xff0c;也要保证对象内部的封装性。迭代器模式提供了一种利用面向对象的遍历方法来遍历对象元素。迭代器模式通过抽象一个迭代器类&#xff0c;不同…

系统卡死问题分析

CPU模式 CPU Frequency Scaling (CPUFREQ) Introduction CPU频率调节设备驱动程序的功能。该驱动程序允许在运行过程中更改CPU的时钟频率。一旦CPU频率被更改,必要的电源供应电压也会根据设备树脚本(DTS)中定义的电压值进行变化。通过降低时钟速度,这种方法可以减少功耗…

伦敦银和伦敦金的区别

伦敦银河伦敦金并称贵金属交易市场的双璧&#xff0c;一般投资贵金属的投资者其实不是交易伦敦金就是交易伦敦银。相信经过一段时间的学习和投资&#xff0c;不少投资者都能分辨二者的区别。下面我们就来谈谈伦敦银和伦敦金有什么异同&#xff0c;他们在投资上是否有差别。 交易…

【Java】树结构数据的搜索

这里写自定义目录标题 需要实现的效果前端需要的json格式&#xff1a;一定是一个完整的树结构错误错误的返回格式错误的返回格式实现的效果 正确正确的返回格式正确的展示画面 后端逻辑分析代码总览 数据库表结构 需要实现的效果 前端需要的json格式&#xff1a;一定是一个完整…
最新文章