《Java编程思想》学习笔记17——注解Annotation

Posted 官小飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Java编程思想》学习笔记17——注解Annotation相关的知识,希望对你有一定的参考价值。

注解Annotation又叫元数据,是JDK5中引入的一种以通用格式为程序提供配置信息的方式。使用注解Annotation可以使元数据写在程序源码中,使得代码看起来简洁,同时编译器也提供了对注解Annotation的类型检查,使得在编译期间就可以排除语法错误。

1JDK内置的3中Annotation:

在JDK5中,内置了3个通用目的的注解Annotation,这三个内置的注解在java.lang包下:

(1).@Override

这个注解常用在继承类或实现接口的子类方法上,表面该方法是子类覆盖父类的方法,该方法的方法签名要遵循覆盖方法的原则:即访问控制权限必能比父类更严格,不能比父类抛出更多的异常。

(2).@Deprecated

这个注解告诉编译器该元素是过时的,即在目前的JDK版本中已经有新的元素代替该元素。

(3).@SuppressWarnings

该注解关闭编译器中不合适的警告,即强行压制编译器的警告提示。

2.注解Annotation的定义:

注解Annotation的定义和接口类似,实际上,编译器也把注解Annotationn像接口一样编译成class字节码文件。例如:

[java]  view plain copy
  1. import java.lang.annotation.*;  
  2.   
  3. @Target(ElementType.METHOD)  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface Test  

像这种没有任何元素的空注解Annotation叫做标记Annotation.

在声明注解的时候往往需要使用@Target,@Retention等注解,这种注解被称为注解的注解(元数据注解),即是专门用于处理注解Annotation本身的。

(1).@Target注解:

用于指示注解所应用的目标程序元素种类,该注解常和ElementType枚举类型一起联合使用,ElementType枚举提供了java程序中声明的元素类型如下:

  1. ANNOTATION_TYPE:注释类型声明。
  2. CONSTRUCTOR:构造方法声明。
  3. FIELD:字段声明(包括枚举常量)。
  4. LOCAL_VARIABLE:局部变量声明。
  5. METHOD:方法声明。
  6. PACKAGE:包声明。
  7. PARAMETER:参数声明。
  8. TYPE::类,接口或枚举声明。

(2).@Retention注解:

该注解用于指示所定义的注解类型的注释在程序声明周期中得保留范围,该注解常和RetentionPolicy枚举联合使用。RetentionPolicy枚举常量定义了注解在代码中的保留策略:

  1. CLASS:编译器把注解记录在类文件中,但在运行时JVM不需要保留注解。
  2. RUNTIME:编译器把注解记录在类文件中,在运行时JVM将保留注解,因此可以通过反射机制读取注解。
  3. SOURCE:仅保留在源码中,编译器在编译时就要丢弃掉该注解。

3.创建和处理自定义注解Annotation:

正常使用注解时,需要在注解中定义元素,用于接收程序设置的值,正常定义注解的例子如下:

[java]  view plain copy
  1. import java.lang.annotation.*;  
  2.   
  3. @Target(ElementType.METHOD)  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface UseCase  
  6.     public int id();  
  7.     public String description() default “no description”;  
  8.   

正常定义注解Annotation的方式类似定义接口,id和description是注解UseCase的属性,而不是方法,注解中不能定义方法只能定义属性。其中description属性有默认的值“no description“,即在使用时如果没有指定description的值,则程序使用其默认值。

上面UseCase注解用于跟踪方法的测试用例说明,使用上面注解的例子如下:

[java]  view plain copy
  1. import java.util.*;  
  2.   
  3. public class PasswordUtils  
  4.     @UseCase(id = 47, description = “Passwords must contain at least one numeric”)  
  5.     public Boolean validatePassword(String password)  
  6.         return (password.mathes(“\\\\w*\\\\d\\\\w*”));  
  7.   
  8. @UseCase(id = 48)  
  9. public String encryptPassword(Srring password)  
  10.     return new StringBuilder(password).reverse().toString();  
  11.   
  12. @UseCase(id = 49, description = “New passwords can’t equal previously used ones”)  
  13. public Boolean checkForNewPassword(List<String> prevPasswords, String password)  
  14.     return !prevPasswords.contains(password);  
  15.   
  16.   

JDK5中提供了Annotation相关的API,结合使用java的反射机制可以实现自定义的Annotation注解处理器(JDK中也提供了使用APT,Annotationprocess tool方式处理注解,在后面会讲解),处理上述Annotation的例子如下:

[java]  view plain copy
  1. import java.lang.reflect.*;  
  2. import java.util.*;  
  3.   
  4. public class UseCaseTracker  
  5.     public static void traceUseCases(List<Integer> useCases, Class<?> clazz)  
  6.         //获取指定类中所有声明的方法  
  7. for(Method m : clazz.getDeclaredMethods())  
  8.     //获取方法上指定类型的注解  
  9.             UseCase uc = m.getAnnotation(UseCase.class);  
  10.             if(uc != null)  
  11.     System.out.println(“Found Use Case:” + uc.id() + “ ” + uc.description());  
  12.     useCases.remove(new Integer(uc.id()));  
  13.   
  14.   
  15. for(int i : useCases)  
  16.     System.out.println(“Warning: Missing use case-” + i);  
  17.   
  18.   
  19. public static void main(String[] args)  
  20.     List<Integer> useCases = new ArrayLis<Integer>();  
  21.     Collections.addAll(useCases, 47484950);  
  22.     trackUseCases(useCases, PasswordUtils.class);  
  23.   
  24.   

输出结果:

Found Use Case:47 Passwords must contain at least onenumeric

Found Use Case:48 no description

Found Use Case:49 New Passwords can’t equal previously usedones

Warning: Missing use case-50

注意:使用反射获取到注解对象之后,类似使用调用方法的方式获取注解的值,如uc.id()等。另外,注解不支持继承,因此声明注解时不能使用extends和implements关键字。

4.Annotation注解元素:

Annotation注解中的元素只能是下面的数据类型:

(1).java的8中基本类型,如int, boolean等等,如果可以自动装箱和拆箱,则可以使用对应的对象包装类型。

(2).String类型。

(3).Class类型。

(4).Enums类型。

(5).Annotation类型。

(6).上面类型的数组。

除了上面这些类型以外,如果在注解中定义其他类型的数据,编译器将会报错。

注意:注解中的元素要么指定默认值,要么由使用的类赋值,如果即没有默认值,使用类也没有赋值的话,注解元素是不会像普通类成员变量一样给定默认值,即必须赋值或者显示指定默认值。默认值例子如下:

[java]  view plain copy
  1. import java.lang.annotation.*;  
  2.   
  3. @Target(ElementType.METHOD)  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface DefaultValue  
  6.     public int id() default -1;  
  7.     public String description() default “”;  
  8.   

5.一个使用Annotation实现ORM的例子:

从EJB3之后,EJB的实体Bean持久化技术被单独抽取出来形成了JPA技术,JPA和Hibernate3之后都支持使用Annotation注解方式进行对象和关系型数据库映射(ObjectRelationship Mapping, ORM),下面使用Annotation注解方式实现一个简单的ORM功能:

(1).相关注解:

[java]  view plain copy
  1. import java.lang.annotation.*;  
  2.   
  3. @Target(ElementType.TYPE)//该注解只能应用在类上  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface DBTable//指定数据库名称  
  6.     public String name() default “”;  
  7.   
  8.   
  9. @Target(ElementType.FIELD)  
  10. @Retention(RetentionPolicy.RUNTIME)  
  11. public @interface Constraints//数据库约束  
  12.     boolean primaryKey() default false;  
  13.     [读书笔记]Java编程思想

    Java后端开发工程师学习笔记狂神说Java笔记

    学习笔记导航

    学习笔记导航

    Java后端开发工程师学习笔记狂神说Java笔记

    JAVA编程思想学习笔记——第一章 对象导论