一、注解
1、概述
注解也是类的一个组成部分。
注解用@来使用。
2、注解的作用
生成帮助信息
@auther 作者
@param 方法参数的介绍
@return 方法返回值的介绍
编译检查
@Override 检查方法是否是重写方法
@FunctionalInterface 检查接口是否是函数式接口
功能型
@Test 单元测试
二、自定义注解
1、定义格式
对于对象,应该先定义类再创建对象
先定义类型:
public class Student{
}
再创建对象:
Student s = new Student();
对于注解,应该先定义注解再使用@
定义注解:
public @interface AAA{
}
使用注解:
@AAA
2、注解的属性
属性的格式
数据类型 属性名();
数据类型
基本数据类型
String
Class
枚举[枚举]
注解
以上类型的数组形式
示例
//注解
public @interface AAA {
//定义属性
int a(); //基本数据类型
String b(); //字符串
Class c(); //Class类型
BBB d(); //注解类型
int[] arr(); //数组形式
String[] srr();
}
——————————————————————————————————————————————————————————————————————————————————————
给属性赋值:
@AAA(a=123,b="美美",c=String.class,d=@BBB,arr={11,22},srr={"abc","def"})
3、注意事项【重要】
-
如果属性有默认值,那么就可以不赋值。---> int age() default 18;
-
如果只有一个属性需要赋值,且属性名字叫value,那么可以直接赋值不需要写键值对。
-
如果数组形式的属性赋值时只有一个元素,那么可以省略大括号。
4、元注解
元注解就是作用在注解上面的注解。
@Target
表示注解可以作用的位置
ElementType.TYPE 作用在类上
ElementType.METHOD 作用在方法上
ElementType.Field 作用在成员变量上
还有很多取值..
如果不写这个元注解,注解就能加在任意位置
@Retention
表示注解可以存活阶段
RetentionPolicy.SOURCE 存活到源码阶段 .java
RetentionPolicy.CLASS 存活到编译后阶段 .class
RetentionPolicy.RUNTIME 存活到运行阶段 运行程序
如果不写这个元注解,注解会存活到CLASS阶段
5、注解完成测试框架
MyApp是自己的一个类,类中有多个方法,我们想测试这些方法有没有异常。
写了一个测试框架,如果要对方法进行测试,只需要给方法加上@Test注解即可。
代码示例:
import java.lang.annotation.Target;
import java.util.ArrayList;
public class MyApp {
//模拟开发过程中自己写了很多方法
//不知道方法有没有bug 进行方法的测试
@Test
public void method01(){
String s = "abc";
s.charAt(10);
}
@Test
public void method02(){
String s = null;
s.charAt(10);
}
@Test
public void method03(){
int[] arr = {11,22,33,44};
arr[3] = 100;
}
public void method04(){
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
for (String s : list) {
list.add("qwe");
}
}
}
//让注解存活到运行阶段
@Retention(RetentionPolicy.RUNTIME)
//让注解只能作用在方法上
@Target(ElementType.METHOD)
public @interface Test {
}
package com.itheima_04;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test测试框架 {
public static void main(String[] args) throws IOException {
//获取MyApp类的字节码对象
MyApp m = new MyApp();
Class c = m.getClass();
//创建流
FileWriter fw = new FileWriter("day14\\bug.txt");
//获取类的所有方法getMethods()
Method[] methods = c.getMethods();
//遍历数组
for (Method method : methods) {
//判断方法上有没有加Test这个注解
if(method.isAnnotationPresent(Test.class)) {
//如果加了注解,让这个方法执行
try {
method.invoke(m);
} catch (Exception e) {
//如果出现了异常,把异常信息输出到文件中
//获取产生反射异常的原因
Throwable throwable = e.getCause();
//获取异常的类型和信息
String s = throwable.toString();
//把信息输出到文件中
//method.getName()是获取方法名
fw.write(method.getName() + "()方法中出现了" + s + "异常");
//换行
fw.write("\r\n");
fw.write("-----------------------------------");
fw.write("\r\n");
}
}
}
//关流
fw.close();
}
}