JAVA中的注解技术(一)
注解技术是JAVA5中的新特性,它为我们在代码中添加信息提供了一种形式化的方法。我们在代码中通过注解的形式添加一些元数据,在将来的某个时刻就可以使用这些元数据。注解在一定程度上把元数据和源代码文件结合在一起,而不是保存在外部文件中。下面我们通过代码来领会注解技术的实现和使用。
一、定义注解
package com.annotation.demo; 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 MyAnnotation { public int id(); public String description() default "no description"; }
首先我们必须导入一些必要的包为我们定义注解提供支撑。我们在定义自己注解时要先使用元注解(@Target和@Retention)对我们自己的注解进行说明。 @Target(ElementType.METHOD) 表示我们定义的注解将用于方法当中
@Retention(RetentionPolicy.RUNTIME) 表示我们的注解在运行时会被使用
二、注解的使用
上面我们定义的注解看起来和定义一个接口很类似。内部定义了两个成员,int和string类型。下面我们先来看看我们如何使用写好的这个注解。
package com.annotation.demo; import java.util.List; public class PasswordUtils { @MyAnnotation(id = 1, description = "abcdefg") public boolean validatePassword(String password) { return (password.matches("\\w*\\d\\w*")); } @MyAnnotation(id = 2) public String encryptPassword(String password) { return new StringBuilder(password).reverse().toString(); }
public void test(){
//TODO
}
@MyAnnotation(id = 4, description = "fefggeff") public boolean checkForNewPassword(List<String> prevPassword, String password) { return !prevPassword.contains(password); } }
因为前面表明我们的注解是用于方法中的,所以我们需将注解写到每个方法的前面。如果写在类的前面,编译器会直接报错。注解中有两个成员,我们可以像代码中所示的那样对其赋值。description是有默认值的,不赋值的话会采用默认值,但id必须赋值。
附:JAVA中注解的元注解
元注解对我们定义的注解进行描述
@Target 表明该注解使用的位置,如ElementType.METHOD
ElementType的参数如下:
CONSTRUCTOR:用于描述构造器
FIELD:用于描述域
LOCAL_VARIABLE:用于描述局部变量
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述参数
TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention 表示需要在什么级别保存该注解,即注解的生命周期,如RetentionPolicy.RUNTIME
RetentionPolicy的参数如下:
SOURCE:注解在源文件可用,但将来会被编译器丢弃
Class:注解在class文件中可用,但将来会被JVM丢弃
RUNTIME:JVM将在运行期间也保留注解,因此可以通过发射机制来读取注解的信息
@Document 将此注解包含在javadoc中
@Inherited 允许子类继承父类中的注解
三、注解的处理
前面我们已经了解到如何定义一个注解以及对其进行使用,但是我们曾提到注解的意义在于将一些原始数据保存到context中。如果我们对其不进行处理,那么注解将毫无意义。下面我们来实现如何从注解中获取原始数据。
package com.annotation.demo; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class UseAnntation { public static void main(String[] args) { List<Integer> myAnnotation = new ArrayList<Integer>(); Collections.addAll(myAnnotation, 1, 2, 3, 4); MyAnnnotationTracker.trackMyAnnotation(myAnnotation, PasswordUtils.class); } } class MyAnnnotationTracker { public static void trackMyAnnotation(List<Integer> myAnnotation, Class<?> c1) { for (Method m : c1.getDeclaredMethods()) { MyAnnotation ma = m.getAnnotation(MyAnnotation.class); if (ma != null) { System.out.println("Found Use Case:" + ma.id() + " " + ma.description()); myAnnotation.remove(new Integer(ma.id())); } } for (int i : myAnnotation) { System.out.println("Warning: Missing usre case-" + i); } } }
我们利用反射的方式获取PasswordUtils类的所有成员方法,通过getAnnotation()来查看该方法是否被添加注解。若添加了注解则输出注解的信息。将上面三部分的功能整合起来,我们可以实现下面的功能。
查找一个类中空方法与非空方法,如果有空方法则给出警告(未使用的注解的方法都被认为空方法)

浙公网安备 33010602011771号