《java编程思想》注解章节的读书笔记
注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据,是java se5加入的新的特性。
基本的7个注解:
三种标准注解:
1.@Override,表示当前的方法定义将覆盖超类中的方法,如果拼写错误或方法签名对不上被覆盖的方法,编译器将报错
2.@Deprecated,如果使用了注解作为他的元素,编译器将发出警告
3.SuppressWarnings,关闭不当的编译器警告信息
四种元注解,元注解用来自定义注解:
1.@Target 表示该注解可以用于什么地方,可能的ElementType参数包括:CONSTRUCTOR:构造器的生命;FIELD:域声明(包含enum实例);LOCAL_VARIABLE:局部变量 声明;METHOD:方法声明;PACKAGE:包声明;PARAMETER:参数声明;TYPE:类、接口(包括注解类型)或enum声明
2.@Retention 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:SOURCE:注解将被编译器丢弃;CLASS:注解在class文件中可用,但会被VM丢弃; RUNTIME:VM将在运行期也保存注解,因此可用通过反射机制读取注解的信息。
3.@Documented 将此注解包含在Javadoc中
4.@Inherited 允许子类继承父类中的注解
自定义注解:
//: annotations/UseCase.java import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UseCase { public int id(); public String description() default "no description"; } ///:~
在上例中标签@UseCase中由UseCase.java定义,其中包括int元素id,以及一个String元素description.注解元素可用的类型如下所示:
.所有基本类型
.String
.Class
.enum
.Annotation
.以上类型的数组
注解应用:
//: annotations/PasswordUtils.java import java.util.*; public class PasswordUtils { @UseCase(id = 47, description = "Passwords must contain at least one numeric") public boolean validatePassword(String password) { return (password.matches("\\w*\\d\\w*")); } @UseCase(id = 48) public String encryptPassword(String password) { return new StringBuilder(password).reverse().toString(); } @UseCase(id = 49, description = "New passwords can!ˉt equal previously used ones") public boolean checkForNewPassword( List<String> prevPasswords, String password) { return !prevPasswords.contains(password); } } ///:~
如果没有注解处理器,注解也不会比注释更有用。java se5扩展了反射机制的API,以帮助程序员构造这类工具,同时还提供了一个外部工具apt帮助程序员解析带有注解的Java源代码。
解析处理器:
//: annotations/UseCaseTracker.java import java.lang.reflect.*; import java.util.*; public class UseCaseTracker { public static void trackUseCases(List<Integer> useCases, Class<?> cl) { for(Method m : cl.getDeclaredMethods()) { UseCase uc = m.getAnnotation(UseCase.class); if(uc != null) { System.out.println("Found Use Case:" + uc.id() + " " + uc.description()); useCases.remove(new Integer(uc.id())); } } for(int i : useCases) { System.out.println("Warning: Missing use case-" + i); } } public static void main(String[] args) { List<Integer> useCases = new ArrayList<Integer>(); Collections.addAll(useCases, 47, 48, 49, 50); trackUseCases(useCases, PasswordUtils.class); } } /* Output: Found Use Case:47 Passwords must contain at least one numeric Found Use Case:48 no description Found Use Case:49 New passwords can!ˉt equal previously used ones Warning: Missing use case-50 *///:~