Annotation学习小结

1、注解的定义

注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。它是对来自像C#之类的其他语言对Java造成的语言特性压力所做出的一种回应。 

注解提供了一条与程序元素关联任何信息或者任何元数据的途径。从某些方面看,注解就像修饰符一样被使用,并应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在注解的“name=value”结构对中。 注解类型是一种接口,能够通过java反射API的方式提供对其信息的访问。

 

2、Java SE5内置的注解

@Deprecated:用该注解注释的程序元素,表明不鼓励程序员使用这样的元素,通常是它很危险或存在更好的选择。

 

@Override:表明当前的方法定义将覆盖超类中的方法。

 

@SuppressWarnings:表明关闭不当的编译器警告信息。

 

还有四种元注解专门负责新注解的创建。

3、元注解

@Target 

表示该注解可以用与生命地方。可能的参数是一个ElementType类型,包括:

CONSTRUCTOR:构造器的声明

FIELD:域的声明

LOCAL_VARIABLE:局部变量声明

METHOD:方法声明

PACKAGE:包声明

PARAMETER:参数声明

TYPE:类、接口(包括注解类型)或者enum类型

 

@Retention

表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:

SOURCE:注解将被编译器丢弃

CLASS:注解在class文件中可用,但会被JVM丢弃

RUNTIME:JVM将在运行期间保留改注解,因此可以用过反射机制读取注解的信息

@Documented

将此注解包含在javadoc中

@Inherited

允许子类继承父类中的注解

 

4、自定义注解

注解的定义看起来很像接口的定义,具体代码如下: 

 

代码
package annotayion;
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 UserCase {
public int id();
public String description() default "no description";
}

 

 

这里定义了一个注解UserCase ,它包含两个元素,id和description,元素的定义类似于方法,description方法有个默认值。

@Target(ElementType.METHOD)表示这个注解是用于方法的,@Retention(RetentionPolicy.RUNTIME)表示这个是运行时都可用。

接下来简单使用该注解构造一个工具类用于密码的验证。

 

代码
package annotayion;
import java.util.List;
public class PasswordUtils {
@UserCase(id
=47, description = "密码必须包含一个数字")
public boolean validatePassword(String password) {
return password.matches("\\w*\\d\\w*");
}
@UserCase(id
=48)
public String encryptPassword(String password) {
return new StringBuilder(password).reverse().toString();
}
@UserCase(id
=49, description = "新的密码等于旧密码")
public boolean checkForNewPassword(List<String> prevPasswords, String password) {
return !prevPasswords.contains(password);
}
}

 

 

最后利用反射,我们可以从类中获取这些注解,打印出其中的参数信息:

 

代码
package annotayion;

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> useCases, Class<?> cl) {
for (Method m : cl.getDeclaredMethods()) {
UserCase uc
= m.getAnnotation(UserCase.class);
if(uc != null) {
System.out.println(
"found user 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);
trackUserCases(useCases, PasswordUtils.
class);
}
}

 

5、注解元素

注解元素可以使用的类型如下:

1)所有基本类型(int,float,boolean等)

2)String

3)Class

4)Enum

5)Annotation

6)以上类型的数组

如果使用了其他类型,编译器就会报错。不允许使用任何包装类型。注解也可以作为元素的类型,也就是说注解可以嵌套。

6、默认值限制

编译器规定,注解的元素不能有不确定的值,也就是说,元素必须要么具有默认值,要么在使用注解的时候提供元素的值。

对于非基本类型的元素,无论是在源代码中声明时,还是在注解接口中定义默认值时,都不能以null作为值。

原文地址:https://www.cnblogs.com/xiziyin/p/1634434.html