day14_Java高级技术
1. 单元测试
1.1 Junit框架
- 单元测试
- 就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试
- Junit单元测试框架
- 可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立
- 不需要程序员去分析测试的结果,会自动生成测试报告出来
- 拥有更强大的测试能力
- 操作步骤
- 将Junit框架的jar包导入到项目中
- 编写测试类、测试类方法,测试方法必须是公共的,无参数,无返回值的非静态方法
- 必须在测试方法上使用@Test注解,用于标注该方法是一个测试方法
- 在测试方法中,编写程序调用被测试的方法即可
- 选中测试方法运行即可,如果测试通过测试标志则是绿色,如果测试失败测试标志则是红色
- 断言方法
Assert.assertEquals()
1.2 Junit常用注解
- Junit 4.xxxx版本
注解 | 说明 |
---|---|
@Test | 测试方法 |
@Before | 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@After | 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeClass | 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。 |
@AfterClass | 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。 |
- Junit 5.xxxx版本
注解 | 说明 |
---|---|
@Test | 测试方法 |
@BeforeEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@AfterEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeAll | 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。 |
@AfterAll | 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。 |
2. 反射
2.1 概述
- 反射
- 以编程的方式获取类中的各种成分,如成员变量、方法、构造器等
- 优势
- 使用反射创建对象,代码更复杂,无视修饰符,功能更强大灵活
- 作用
- 可以在运行时得到一个类的全部成分然后操作
- 可以破坏封装性
- 更重要的用途是适合:做Java高级框架。基本上主流框架都会基于反射设计一些通用技术功能
2.2 获取元素
2.2.1 获取类
- 获取类是反射的第一步,即就是得到加载后的类对象
实现
// 方式一:直接获取
Class c1 = 类名.class;
// 方式二:Object提供的方法:public Class getClass()
Class c2 = 对象.getClass()
// 方式三:调用Class提供方法:public static Class forName(String package);
Class c3 = Class.forName(“全类名”);
2.2.2 获取类的构造器
- Class提供了从类中获取构造器的方法
方法 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有构造器对象的数组(只能拿public的) |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造器对象的数组,存在就能拿到 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个构造器对象(只能拿public的) |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造器对象,存在就能拿到 |
- 获取到构造器的作用:依然是初始化一个对象返回
符号 | 说明 |
---|---|
T newInstance(Object... initargs) | 根据指定的构造器创建对象 |
public void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
- 作用
- 创建对象
- 如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象,即利用反射破坏封装性,执行非公开的构造器
2.2.3 获取类的成员变量
- Class提供了从类中获取成员变量的方法
方法 | 说明 |
---|---|
public Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
public Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
public Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
public Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
- 获取到成员变量的作用:依然是赋值、取值
方法名 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 取值 |
public void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
- 作用
- 在某个对象中取值和赋值
- 如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
2.2.4 获取类的成员方法
- Class提供了从类中获取成员方法的方法
方法 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
- 获取到成员方法的作用:依然是执行该方法
方法名 | 说明 |
---|---|
public Object invoke(Object obj, Object... args) | 触发某个对象的该方法执行。 |
public void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
- 作用
- 在某个对象中触发该方法执行
- 如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
3. 注解
3.1 自定义注解
-
注解
- 就是Java代码里的特殊标记
- Java程序中的类上、构造器上、方法上、成员变量上、参数、等都可以用注解进行标记
-
作用
- 对Java中类、方法、成员变量做标记,然后进行特殊处理
-
自定义注解
- 属性类型只能是一下类型或该类型的一维数组
- 基本数据类型
- String
- Class
- 注解
- 枚举
- value
- value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
- 如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的
- 属性类型只能是一下类型或该类型的一维数组
// 自定义注解
public @interface 注解名称 {
public 属性类型 属性名() default 默认值;
}
// 使用注解
@注解名(属性名1=值1, 属性名2=值2...)
3.2 元注解
- 就是修饰注解的注解
- 元注解有两个
@Target
:约束自定义注解只能在哪些地方使用@Retention
:申明注解的生命周期
@Target
中可使用的值定义在ElementType枚举类中,常用值如下
TYPE
,类,接口FIELD
,成员变量METHOD
,成员方法PARAMETER
,方法参数CONSTRUCTOR
,构造器LOCAL_VARIABLE
,局部变量
@Retention
中可使用的值定义在RetentionPolicy枚举类中,常用值如下
SOURCE
:注解只作用在源码阶段,生成的字节码文件中不存在CLASS
: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值RUNTIME
:注解作用在源码阶段,字节码文件阶段,运行阶段
3.3 注解的解析
-
注解的解析
- 注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
-
与注解解析相关的接口
Annotation
:注解的顶级接口,注解都是Annotation类型的对象AnnotatedElement
:该接口定义了与注解解析相关的解析方法
方法 说明 Annotation[] getDeclaredAnnotations()
获得当前对象上使用的所有注解,返回注解数组。 T getDeclaredAnnotation(Class<T> annotationClass)
根据注解类型获得对应注解对象 boolean isAnnotationPresent(Class<Annotation> annotationClass)
判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false -
所有的类成分Class、Method、Field、Constructor都实现了AnnotatedElement接口,他们都拥有解析注解的能力
4. 动态代理
-
代理
- 代理思想就是被代理者没有能力,或者不愿意去完成某件事情,需要找个人(代理)代替自己去完成这件事
- 是一个用来对被代理对象的行为进行增强的对象
-
动态代理
- 动态代理主要是对被代理对象的行为进行代理,对功能进行增强
-
Java中代理的代表类是
java.lang.reflect.Proxy
,它提供了一个静态方法,用于为被代理对象,产生一个代理对象返回public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
- 参数一:类加载器,加载代理类,产生代理对象
- 参数二:真实业务对象的接口,被代理的方法交给代理对象
- 参数三:代理的核心处理程序
-
实现动态代理的步骤
- 必须存在接口
- 被代理对象需要实现接口
- 使用Proxy类提供的方法,为被代理对象创建一个代理对象
-
代理对象调用方法的执行流程
- 先走向代理
- 代理中可以真正触发被代理对象的方法执行
- 回到代理中,由代理负责返回结果给调用者
-
动态代理的优点
- 可以在不改变方法源码的情况下,实现对方法功能的增强,提高了代码的复用
- 简化了编程工作、提高了开发效率,同时提高了软件系统的可扩展性
- 可以为被代理对象的所有方法做代理
- 非常的灵活,支持任意接口类型的实现类对象做代理