一、单元测试(Junit)
定义:针对代码的最小单元(方法)进行测试
优点:方便、灵活性强
使用方式:通过编写测试方法调用需要被测试的方法,并在测试方法上添加@Test注解,点击方法右键进行运行即可完成
相关注解:
@Test:测试方法
@Before:在所有测试方法之前均执行一次
@After:在所有测试方法之后均执行一次
@BeforeClass:在所有测试方法之前只执行一次-----------》对应静态方法
@AfterClass:在所有测试方法之后只执行一次-----------》对应静态方法
注意事项:编写的测试方法必须为public、空参、无返回值的方法
示列:
@BeforeClass
public static void beforeCalls(){
System.out.println("所有方法之前执行一次******");
}
@AfterClass
public static void afterCalss(){
System.out.println("所有方法之后执行一次*********");
}
@Before
public void before(){
System.out.println("每个方法之前执行一次");
}
@After
public void after(){
System.out.println("每个方法之后执行一次");
}
@org.junit.Test
public void method(){
printArr(new int[10]);
System.out.println("方法1");
}
@org.junit.Test
public void method2(){
Assert.assertEquals(10,printArr(new int[10]));
System.out.println("方法2");
//printArr2(new String[20]);
}
public int printArr(int[] arr){
// System.out.println(arr.length);
// for (int i = 0; i < arr.length; i++) {
// System.out.println(arr[i]);
// }
return arr.length;
}
public void printArr2(String[] arr){
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
}
二、反射
定义(作用):通过对象或类名获得相应字节码文件(.Class),并通过解析可获得该类中的所有属性、方法、构造。
应用场景:一般用于开发框架
1、通过对象或类名获取.class文件的对象:
Class<?> aClass = Class.forName("Day16.Demo1.Student");
Class<Student> studentClass = Student.class;
Student student = new Student();
Class<? extends Student> aClass1 = student.getClass();
2、通过Class对象获取相应的构造器:
//获取所有公有构造
System.out.println("获取所有公有构造");
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("获取所有构造,包括私有");
//获取所有构造,包括私有
Constructor<?>[] dcs = aClass.getDeclaredConstructors();
for (Constructor<?> dc : dcs) {
System.out.println(dc);
}
//获取指定公有构造
System.out.println("获取指定公有构造");
Constructor<?> constructor = aClass.getConstructor();
System.out.println(constructor);
//获取指定构造(任意修饰符)
System.out.println("获取指定构造(任意修饰符)");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class,int.class);
System.out.println(declaredConstructor);
//创建对象
declaredConstructor.setAccessible(true);
Student stu = (Student) declaredConstructor.newInstance("wzp", 18);
System.out.println(stu);
3、通过Class对象获取属性
Class<? extends Student> aClass = new Student().getClass();
System.out.println("获取所有公有属性");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("获取所有属性(含非公)");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("根据属性名获取属性(公有)");
Field gender = aClass.getField("gender");
System.out.println(gender);
System.out.println("根据属性名获取属性(含非公)");
Field name = aClass.getDeclaredField("name");
System.out.println(name);
Constructor<? extends Student> constructor = aClass.getConstructor();
//根据构造方法创建对象
Student student = constructor.newInstance();
name.setAccessible(true);//取消权限检查
name.set(student, "wzp");//调用方法
System.out.println(student);
String value = (String) name.get(student);
System.out.println(value);
4、通过Class对象获取所有方法:
Class<? extends Student> aClass = Student.class;
System.out.println("获取所有公有方法,包括父类");
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取所有方法(包括非公有),不包括父类");
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("根据方法名和参数列表获取指定公有方法");
Method setName = aClass.getMethod("getName");
System.out.println(setName);
System.out.println("根据方法名和参数名获取指定方法(含非公)");
Method setName1 = aClass.getDeclaredMethod("setName", String.class);
System.out.println(setName1);
Student student = aClass.getConstructor().newInstance();
setName1.setAccessible(true);
//无返回值方法调用
setName1.invoke(student,"天霸");
Method getName = aClass.getDeclaredMethod("getName");
getName.setAccessible(true);
//调用有返回值的方法
Object invoke = getName.invoke(student);
System.out.println(invoke);
三、注解
定义:Java注解是代码的特殊标记,例如@OverRide代表重载,@Test代表测试
作用:让其他程序根据注解信息决定该怎么执行该程序
自定义注解:
格式:public @interface 注解名{
public 属性类型 属性名()default 对应值;
}
示例:
public @interface MyTest{
String aaa();
boolean bbb() default true; //default true 表示默认值为true,使用时可以不赋值。
String[] ccc();
}
元注解:对应注解的注解
元注解常用类型及作用:
注解解析:
1、获取Class对象及其内部以及添加注解的方法或属性
2、通过Class对象或Method对象.isAnnotationPresent(注解名.class),判断是否存在对象
3、Class对象或Method对象.getDeclaredAnnotation(注解名.class),获得注解对象
4.在通过注解对象调用其属性,即可获得注解属性值
示例:
//获得Class对象
Class<My_AnnoTest> aClass = My_AnnoTest.class;
//取得Class对象中的指定方法
Method method = aClass.getDeclaredMethod("method");
//判断该方法是否存在相应注解
if (method.isAnnotationPresent(Anno.class)){
//获得注解对象
Anno anno = method.getDeclaredAnnotation(Anno.class);
//得到注解的属性值
System.out.println(anno.age());
System.out.println(anno.name());
System.out.println(anno.value());
}
}
@Anno(value = "dancer",age = 18)
void method(){}
四、动态代理
作用:在不改变对象原有功能及层级结构的情况下对该对象的功能进行增强
生成动态代理:通过Proxy类的newInstance(...)方法可以为实现了同一接口的类生成代理对象,调用方法时需要传递三个参数
源码示例:
public static Star getProxy(SuperStart superStart){
//返回实现了与SuperStart相同接口(Star)的代理对象
return (Star) Proxy.newProxyInstance(SuperStart.class.getClassLoader(), new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("sing".equals(method.getName())){
System.out.println("演唱会准备工作");
}else if ("dance".equals(method.getName())){
System.out.println("跳舞前准备工作");
}
return method.invoke(superStart);
}
});
}