注解(也被称为元数据)为我们在代码中添加信息提供了一些形式化的方法,是我们在稍后的某个时刻,可以非常方便的使用这些数据
注解的语法比较简单,除了@符号使用之外,他与java语法一致,javaSE5内置了三种,java.lang中的注解
- @Override 表示当前的方法定义将覆盖超类中的方法
- @Deprecated 如果程序员使用了注解为他的元素,那么编译器将发出警告信息
- @SuppressWarnings 关闭不当的编译器警告信息
一. 基本语法
import org.junit.Test;
public class TestTable {
public void excute(){
System.out.println("");
}
@Test
public void testExecute(){
}
}
可以看出被注解的方法与其他方法并无区别,注解@Test可以与任何修饰符作用于方法
二. 定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) //表示注解应用于方法
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
}
可以看出注解的定义很像接口的定义,他与java接口一样会编译成class文件,定义注解时,会需要一些元注解,如:@Target,@Retention
- @Target 用来定义你的注解应用在什么地方(例如是一个方法还是类)
- @Rectetion 用来定义注解在哪一级别可用,在源代码中(SOURCE),类文件中(CLASS)或者运行时(RUNTIME)
三. 原注解
java 目前只内置了三种标准注解,四种原注解
注解 | 说明 |
---|---|
@Target | 表示该注解可用于什么地方。可能的ElementType的参数包括:CONSTRUCTOR:构造器的说明 FIELD:域说明(包括enum实例) LOCAL_VARIABLE 局部变量声明 METHOD:方法声明 PACKAGET:包的说明 PARAMETER:参数的说明 TYPE:类或接口 |
@Retention | 表示需要在什么级别保存该信息 。可选的RetentionPolicy: SOURCE:注解将被编译器丢弃 CLASS:注解将在CLASS文件中可用,但在VM中将被丢弃 RUNTIME:VM将在运行期也保留注解,因此可用通过反射机制读取注解的信息 |
@Docemented | 将此注解包含在javadoc中 |
@Inherited | 表示子类允许继承父类的注解 |
四. 编写注解处理器
如果没有用来读取注解的工具,那么注解也不会比注释更有用。在javaSE5扩展了反射机制的API,以帮助程序员实现这类工具
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//@Retention 用来定义该注解在哪一级可以用
//@Target元注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserCase {
public int id();
public String description() default "no description";
}
public class PasswordUtils {
@UserCase(id=10,description="validatePassword")
public boolean validatePassword(String password){
return(password.matches("\\w*\\d\\w*"));
}
@UserCase(id=18)
public String encryptPassword(String password){
return new StringBuilder(password).reverse().toString();
}
@UserCase(id=108,description="checkForNewPassword")
public boolean checkForNewPassword(String password){
return true;
}
}
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UserCaseTracker {
public static void trackUserCases(List<Integer> userCase,Class<?> cl){
for(Method m : cl.getDeclaredMethods()){
UserCase u = m.getAnnotation(UserCase.class);
if(u != null){
System.out.println("Found Use UserCase:"+u.id()+"\t"+u.description());
userCase.remove(new Integer(u.id()));
}
}
for(int i : userCase){
System.out.println("Miss user UserCase "+i);
}
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 16,108,10,50);
trackUserCases(list,PasswordUtils.class);
}
}
五. 编写注解处理器
标签@UserCase由UserCase.java定义,其中包含int元素id,String元素description,注解的可用类型如下所示:
- 所有的基本类型(int,float,boolean等)
- String
- Class
- Annotation
- 以上类型的数组
注意:元素不能有不确定的值,要么具有默认的值,要么给元素提供元素的值