SE高阶(12):Annotation(注解)的简单了解和使用
2017-04-28 00:26
267 查看
(一)Annotation(注解)的作用
注解的作用是修饰编程元素。编程元素就是:包、类、构造方法、方法、成员变量等。Annotation能对这些元素进行标识,JVM在执行时可以读取标识并执行相应处理。注解和注释是不同的,区别:注解可以在源文件中加入一些信息,例如使用框架开发时,我们都是通过配置文件进行对象关系组合映射等功能,而通过注解就可以代替配置文件的编写,而注释是开发人员用于方便阅读源代码,不会对程序产生任何影响。总结一句话:注解给JVM看,注释给开发人员看。
注解的基本功能
编写文档:通过代码里标识的元数据生成文档。代码分析:通过代码里标识的元数据对代码进行分析。
编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。
(二)Java内置注解
Java内置注解是JDK提供的普通注解,在eclipse中可以通过输入@ + alt+/来查看内置注解。除了之外,我们还可以自定义注解,以便用于不同情况。常用的内置注解:
@Override(重写):标示该方法重写了超类方法或实现了接口类方法;
@Deprecated(弃用、不赞成):表示修饰的方法已被弃用,不赞成使用;
@SuppressWarnings(抑制警告) :让编译器取消警告提醒(即感叹号信息);
@FunctionalInterface(函数接口):Java8新增注解,修饰接口表明只能存在一个抽象方法,但是允许存在多个默认方法;
@SafeVarargs(heap pollution):修饰出现堆污染的情况,如可变形参、泛型数组。
//测试常用的内置注解 public class Test00 extends supClass implements SupImp{ @Override public void testMethod() { System.out.println("~~~~~~~~"); } @Override public void method2() {}//该方法没重写超类方法或实现接口方法,检查报错 @Override public void impAbc() {}//标识该方法实现了接口方法 } class supClass{ @Deprecated//修饰的方法会被划横线,表示不赞成使用 public void testMethod(){} } @FunctionalInterface interface SupImp{ void impAbc(); // void impAbc2();//接口中抽象方法超过一个就会报错 }
(三)元注解
注解分为普通注解和元注解,两者区别:普通注解就是JDK提供的基本注解和自定义的注解,只能注解代码;元注解是修饰注解的注解。使用eclipse可以通过F3查看Java的内置注解的源代码,修饰该注解的注解就是要了解的元注解了。Java目前提供的元注解如下:
@Documented:修饰的注解可以被Javadoc工具提取成文档;
@Inherited:修饰的注解具有继承性,被修饰的注解修饰一个普通类,该类的子类可以继承父类的注解;
@Repeatable(Java8新增):标识某个注解可以重复使用,但需要一个容器注解的Class实例;(重复注解:允许某个注解可重复使用)
@Target:修饰的注解会被限制使用范围,表示该注解可以用在什么地方,ElementType参数如下:
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
@Retention:表示在什么级别保存该注解信息,修饰的注解具有生命周期。RetentionPolicy参数如下:
SOURCE:注解只保留在源代码中(xx.java),会被编译器直接丢弃
CLASS:注解保留在class文件中,运行时会被JVM丢弃,不可获取信息。作为默认值。
RUNTIME:JVM运行时保留该注解,因此可以通过反射机制读取注解的信息。
@Documented案例
@Documented//该注解能被提取成文档 @Retention(RetentionPolicy.RUNTIME) @interface AnnoDocu {} public class TestMetaAnno { @AnnoDocu public String str; @AnnoDocu public int num; @AnnoDocu public void method1() { } }使用Javadoc工具提取TestMetaAnno类,@AnnoDocu注解也会被提取到文档中。要注意javadoc 只能为 public和 protected 成员处理注释文档。
@Inherited案例
@Inherited//修饰的注解允许被继承 @Retention(RetentionPolicy.RUNTIME)//保留到运行时 @interface AnnoInher {} @AnnoInher class Father{ } public class Son extends Father{ public static void main(String[] args) throws Exception { //获取Son类中所有注解,包括父类的。getDeclared只作用于本身,得不到父类注解 Annotation[] an = Son.class.getAnnotations(); //把该注解数组转成字符串 System.out.println(Arrays.toString(an)); //判断指定的注解是否在Son.class实例对应的类中 System.out.println(Son.class.isAnnotationPresent(AnnoInher.class)); } }
@Rentention案例
//如果普通注解没使用@Retention,默认使用CLASS。所以自定义注解时最好使用RUNTIME @Retention(RetentionPolicy.SOURCE)//保留到源代码中(.java),编译期间就被丢弃 @Retention(RetentionPolicy.CLASS)//保留到类文件中(.class),运行时被JVM丢弃 @Retention(RetentionPolicy.RUNTIME)//保留到运行时 @interface RetentionTest { }
@Target案例
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)//限制该注解只能用于类、接口、枚举 @interface TargetTest {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.CONSTRUCTOR)//限制该注解只能用于构造器 @interface TargetTest2 {} //其他参数就不一一演示,使用方式都一样 @TargetTest public class TestMetaAnno { @TargetTest2 public TestMetaAnno() {} }
@Repeatable案例
该注解是Java8新增的,使重复注解看起来更加简洁明了。下面有对比代码://Java8之前的重复注解方式,使用一个注解来存储另一个注解 @Retention(RetentionPolicy.RUNTIME) @interface Books{ Book[] value();//用数组存储@Book注解 } @interface Book{ String value(); } //如果注解数量多,可读性会很差,写起来很麻烦 @Books({@Book("A"), @Book("B")}) public class TestMetaAnno { }
//Java8新特性:@Repeatable @interface Books{ Book[] value(); } @Repeatable(Books.class)//标识该注解可重复使用,以@Books作为容器注解存储@Book @interface Book{ String str(); } public class TestMetaAnno { //逻辑清晰,可读性很高 @Book(str = "A") @Book(str = "B") @Book(str = "C") public void method() {System.out.println("~~~~");} }
(四)自定义注解
自定义注解看起来和接口的定义方式差不多,以@interface作为标识。自定义注解与JDK提供的普通注解并无两样,都可以用于修饰任何程序元素。注解中还可以声明成员变量。//自定义注解 public @interface MyAnno { }
//给注解定义成员变量 public @interface MyAnno { String value(); String 4000 str(); int num(); }
使用说明:注解中定义成员变量方式看起来和接口中的抽象方法差不多。但在注解中,返回值是变量类型,方法名是变量名,不允许传入参数。如果只定义了成员变量,并且变量名是value,则可以直接赋值。例如元注解@Retention(RetentionPolicy.RUNTIME)。
自定义注解使用案例
@MyAnno //注解类 public class AnnoTest { @MyAnno//注解方法 public void method00() { System.out.println("======"); } public static void main(String[] args) throws NoSuchMethodException, SecurityException { Class cla = AnnoTest.class; Method me = cla.getMethod("method00"); Annotation[] anCl = cla.getAnnotations();//获取类的所有注解 Annotation[] anMe = me.getAnnotations();//获取指定Method对象的所有注解 for(Annotation a : anCl) System.out.println("类中的注解:" + a); //没有注解可输出 for(Annotation a : anMe) System.out.println("Method实例中的注解:" + a.toString()); } }
使用说明:输出结果会发现没有获取到注解信息,这是因为注解的生命周期默认都是保存在class文件中,运行时就丢弃了,所以获取不了,想要通过反射得到注解信息就需要使用元注解@Retention来修饰普通注解,例如@Rentention(RetentionPolicy.RUNTIME)。
相关文章推荐
- 初步了解jackson,简单的使用jackson的annotation
- Java基础复习笔记12Java自定义注解Annotation的使用
- 简单了解PHP编程中数组的指针的使用
- 注解(Annotation)源码解析--简单实现(Hibernate,EJB,JPA)
- 简单了解文档碎片DocumentFragment的使用
- 对于对象的简单验证及返回处理——@JsonView ,@Valid注解的使用
- 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
- redis简单了解和使用
- springMVC注解的简单使用
- 使用@Controller注解为什么要配置<mvc:annotation-driven />
- Java自定义注解Annotation的使用
- Git使用:小白入门要了解的内容简单介绍
- 使用aop代理获取不到Annotation注解问题
- JAVA中注解的简单使用
- [教程]自定义Annotation之一入门篇(定义简单的注解)
- Java 注解(Annotation)使用方法归纳
- 简单自定义Annotation和利用反射获取注解中的值
- 简单了解Django模板的使用
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
- Memcached 简单利用和简单了解(Mac的安装和使用)