目录
一、Junit单元测试
1.什么是单元测试
Junit是一个Java语言的单元测试框架,属于白盒测试,简单理解为可以用于取代java的main方法。Junit属于第三方工具,需要导入jar包后使用。
2.Junit的使用步骤
(1)编写测试类,简单理解Junit可以用于取代java的main方法
(2)在测试类方法上添加注解 @Test
(3)@Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
(4)添加Junit库到lib文件夹中,然后进行jar包关联
3.单元测试中其它四个注解
@Before:修饰的方法会在测试方法之前被自动执行
@After:修饰的方法会在测试方法执行之后自动被执行
@BeforeClass:在所有的测试方法运行之前,只运行一次,而且必须用在静态方法上。
@AfterClass:在所有的测试方法运行之后,只运行一次,而且必须用在静态方法上。
二、反射
1.类的加载
当类的字节码文件被加到内存之后,JVM自动为之创建一个对象(该对象中保存字节码的所有信息),这个对象我们一般称为字节码文件对象或者Class对象
2.什么是反射
获取Class对象,解剖它,从中取出构造方法,成员变量,成员方法,进而使用它们。
3.反射在实际开发中的应用
(1)编写各种IDE(IDEA,Eclipse)
(2)编写各种框架
4.反射中万物皆对象的概念
(1)字节码文件:Class对象
(2)构造方法:Constructor对象
(3)成员方法:Method对象
(4)成员变量:Field对象
(5)newInstance:创建对象
(6)invoke:执行/调用

5.反射的第一步获取字节码文件对象(Class对象)

6.Class对象中的三个常用方法
String getSimpleName(); 获得简单类名,只是类名,没有包
String getName(); 获取完整类名,包含包名+类名
T newInstance() ;创建此 Class 对象所表示的类的一个新实例。要求:类必须有public的无参数构造方法
newInstance()方法在JDK1.9之后过时了,需用下述方法替代:
clazz.getDeclaredConstructor().newInstance()
7.通过反射获取构造方法
(1)Constructor getConstructor(Class... parameterTypes)
根据参数类型获取构造方法对象,只能获得public修饰的构造方法。
如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。
(2)Constructor getDeclaredConstructor(Class... parameterTypes)
根据参数类型获取构造方法对象,包括private修饰的构造方法。
如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。
(3)Constructor[] getConstructors()
获取所有的public修饰的构造方法
(4)Constructor[] getDeclaredConstructors()
获取所有构造方法,包括private修饰的构造方法
8.Constructor类中常用方法
(1)T newInstance(Object... initargs)
根据指定参数创建对象。
(2)void setAccessible(true)
暴力反射,设置为可以直接访问私有类型的构造方法。
9.通过反射获取成员方法
(1)Method getMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,只能是获取public修饰的
(2)Method getDeclaredMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,包括private修饰的
(3)Method[] getMethods()
获取所有的public修饰的成员方法,包括父类。
(4)Method[] getDeclaredMethods()
获取当前类中所有的方法,包含私有的,不包括父类。
10.Method类中常用方法
(1)Object invoke(Object obj, Object... args)
根据参数args调用对象obj的该成员方法
如果obj=null,则表示该方法是静态方法
(2)void setAccessible(boolean flag)
暴力反射,设置为可以直接调用私有修饰的成员方法
11.通过反射获取成员属性(了解)
public Field[] getFields():获取public修饰的所有的变量对象
public Field[] getDeclaredFields():获取所有的变量对象,包括私有
public Field getField(String name):获取指定变量名的public修饰的变量对象
public Field getDeclaredField(String name):获取指定变量名的变量对象,包括私有
12.Field类中常用方法(了解)
(1)Object get(Object obj):返回由该 Field表示的字段在指定对象上的值。
(2)void set(Object obj, Object value):将指定的对象参数中由此 Field对象表示的字段设置为指定的新值。
(3)void setAccessible(boolean flag) 将此反射对象的 accessible标志设置为指示的布尔值。
(4)Class<?> getType():返回一个 Class对象,标识由该 Field对象表示的字段的声明类型。
三、注解
1. JDK1.5的新特性
一种标记,标记在类中,接口中,方法上,变量上。
2.注解的两个作用
(1)编译检查
(2)框架的配置文件
3.常用注解介绍
@override(编译检查方法重写是否正常)
@FunctionalInterface:编译检查是否符合函数式接口的要求(只有一个抽象方法)
@Oeprecated:编译检查是否过时
4.自定义注解
格式:
public @interface 注解名称{
属性列表;
}
5.给自定义注解添加属性
(1)属性的作用
可以让用户在使用注解时传递参数,让注解的功能更加强大。
(2)属性的格式
格式:格式1:数据类型 属性名();
格式2:数据类型 属性名() default 默认值;
(3)属性定义实例
public @interface Student {
String name(); // 姓名
int age() default 18; // 年龄
String gender() default "男"; // 性别
}
// 该注解就有了三个属性:name,age,gender
(4)属性适用的数据类型
八种基本数据类型(int,float,boolean,byte,double,char,long,short)
String类型,Class类型,枚举类型,注解类型
以上所有类型的一维数组
6.使用自定义注解
(1)定义一个注解:Book
包含属性:String value() 书名
包含属性:double price() 价格,默认值为 100
包含属性:String[] authors() 多位作者
(2)使用注解
public class BookShelf {
@Book(value = "西游记",price = 998,authors = {"吴承恩","白求恩"})
public void showBook(){
}
}
(3)注意事项
①如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。
②如果属性没有默认值,那么在使用注解时一定要给属性赋值。
③属性的出现顺序随意
④如果属性是数组,那么需要使用{}括起来
7.自定义注解中的特殊属性名
(1)当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给属性值,无论value是单值元素还是数组类型。
(2)如果注解中除了value属性还有其他属性,且至少有一个属性没有默认值,则在使用注解给属性赋值时,value属性名不能省略。
8.注解之元注解
@Target
@Retention
(1)@Target元注解
作用:指明此注解用在哪个位置,如果不写默认是任何地方都可以使用。
TYPE: 用在类,接口上
FIELD:用在成员变量上
METHOD: 用在方法上
PARAMETER:用在参数上
CONSTRUCTOR:用在构造方法上
LOCAL_VARIABLE:用在局部变量上
注意:以上六种属性,是ElementType枚举类中的静态成员
(2)@Retention元注解
作用:定义该注解的生命周期(有效范围)。
SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了。
CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值。
RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解。
注意:以上三种属性,是RetentionPolicy枚举类中的静态成员
9.注解的解析
通过Java技术获取注解数据的过程则称为注解解析。
(1)确定注解所在的对象
如果注解在类上,获取该类的字节码文件对象
如果注解在构造上,先获取字节码文件对象,再获取那个构造方法对象
如果注解在成员方法上,先获取字节码文件对象,再获取那个成员方法对象
如果注解在成员变量上,现获取字节码文件对象,再获取那个成员变量对象
(2)确定注解是否真实存在,获取该注解对象
Anontation:所有注解类型的公共接口,类似所有类的父类是Object。
AnnotatedElement:定义了与注解解析相关的方法,常用方法以下四个:
boolean isAnnotationPresent(Class annotationClass); 判断当前对象是否有指定的注解,有则返回true,否则返回false。
T getAnnotation(Class<T> annotationClass); 获得当前对象上指定的注解对象。
Annotation[] getAnnotations(); 获得当前对象及其从父类上继承的所有的注解对象。
Annotation[] getDeclaredAnnotations();获得当前对象上所有的注解对象,不包括父类的。
10.注解综合练习
模拟Junit高级版本,自定义注解时,有一个属性,加value
需求:执行main方法,让Calculate类中被MyTest注解修饰的方法运行,value值是几就运行几次,其他方法不运行
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {
int value();
}
public class MyMethods {
public void method1(){
System.out.println("method1");
}
@MyTest(3)
public void method2(){
System.out.println("method2");
}
@MyTest(5)
public void method3(){
System.out.println("method3");
}
public void method4(){
System.out.println("method4");
}
}
//获取加了注解的MyMethods类
MyMethods methods = new MyMethods();
//获取该类的字节码文件
Class<? extends MyMethods> clazz = methods.getClass();
//通过反射得到该类对象
MyMethods myMethods = clazz.getDeclaredConstructor().newInstance();
//通过反射得到所有方法
Method[] methods1 = clazz.getMethods();
//遍历判断是否有MyTest注解存在
for (Method method : methods1) {
if (method.isAnnotationPresent(MyTest.class)) {
//如果存在,获取value属性值,执行相应次数的方法
MyTest annotation = method.getAnnotation(MyTest.class);
int value = annotation.value();
for (int i = 0; i < value; i++) {
method.invoke(myMethods);
}
}
}
1165

被折叠的 条评论
为什么被折叠?



