元注解: 专职负责注解其他的注解
@Target
: 表示该注解可以用于什么地方,可用的ElementType参数包括:
CONSTRUCTIOR
: 构造器的声明FIELD
: 域声明(包括enum实例)LOCAL_VARIABLE
: 局部变量声明METHOD
: 方法声明PACKAGE
: 包声明PARAMETER
: 参数声明TYPE
: 类、接口(包括注解类型)或enum声明
@Retention
: 表示需要在级别保存该注解类型,可选的RetetionPolicy参数包括:
SOURCE
: 注解将被编译器丢弃CLASS
: 注解在class文件中可用,但会被VM丢弃RUNTIME
: VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
注解元素: 注解元素可用的类型如下
- 所有的基本数据类型(int, float, boolean等)(不允许使用包装类)
String
Class
enum
Annotation
- 以上类型的数组
定义一个注解,并设置默认值
@Target(ElementType.METHOD)
@Retention(RetetionPolicy.RUNTIME)
public @interface @SimulatingNull{
public int id() default -1;
public String description() default "";
}
用法
如果注解中仅有一个元素无默认值(需要赋值),此时无需使用名-值对的这种语法
实例
/**
* 模拟JUnit实现单元测试
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
/**
* @Test注解处理器
*/
class TestProcessor {
public static void process(Class cl) {
try {
Object obj = cl.newInstance();
for(Method method: cl.getDeclaredMethods()) {
// System.out.println("--> "+method.getName());
Annotation[] anns = method.getDeclaredAnnotations();
if(anns.length < 1)
continue;
if(anns[0] instanceof Test) {
System.out.println("==== [Testing]: " + method.getName() + " ====");
try {
method.invoke(obj);
} catch (java.lang.reflect.InvocationTargetException e) {
e.printStackTrace();
}
}
}
System.out.println("==== you have passed this test. ====");
} catch(InstantiationException|IllegalAccessException e) {
e.printStackTrace();
}
}
}
class NeedTest {
@Test
public void run() {
System.out.println("I'm running my Test...");
}
}
public class Client {
public static void main(String[] args) {
TestProcessor.process(NeedTest.class);
}
}