JAVA之Annotation (一)

来源:互联网 发布:剑三霸刀正太捏脸数据 编辑:程序博客网 时间:2024/04/28 10:04

概述

从JDK1.5开始,JAVA增加了对元数据(MetaData)的支持,也就是Annotation(注解或注释)。Annotation是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并进行相应的处理。
通过注释,开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具、部署工具可以通过这些补充信息进行验证或进行部署。

Annotation类似于修饰符,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被存储在Annotation的"name=value"对中。
如果使用注解时只需要为value成员变量指定值,则使用该注解时可以在该注解后面的括号指定value值,而无需写“value=变量值”的形式。

Annotation可以用于设置元数据,但不影响程序代码的运行,无论增加、删除Annotation,代码始终如一的运行。如果希望让程序中的Annotation在运行时起一定的作用,只有通过某种配套的工具对Annotation中的信息进行访问和处理,访问和处理Annotation的工具统称APT(Annotation Processing Tool)

基本Annotation

@Override

@Override就是用来指定方法重载的,它可以强制一个子类必须覆盖父类的方法。如果没有成功重写(可能是方法名、参数写错,可能是父类没有该方法等),编译器就会报错。

@Deprecated

@Deprecated用于表示某个程序元素(类、方法)已过时,当其它程序使用已过时的类、方法时,编译器会给出警告。
class Apple{@Deprecatedpublic void info(){System.out.println("该方法已过时");}}public class DeprecatedTest {public static void main(String []args){Apple a=new Apple();a.info();}}
结果正常输出,但编译器发出警告

@SuppressWarnings

@SuppressWarnings只是被该Annotation修饰的程序元素(以及该程序元素中所有的子元素)取消显示指定的编译警告。@SuppressWarnings会一直作用在该程序的所有元素上。

可以看出,当没有使用@SuppressWarnings注释时,new ArrayList()下面有淡淡的红线,这表明系统提出的警告,我们看一下警告的内容。

那么如果为ls或main()添加了@SuppressWarnings “rawtypes”呢?

不幸的是,还是有警告。这一次看一看警告的内容:
好吧,再加
这下总算弄好了,不过如果在一个类、方法、成员变量前加多个@SuppressWarnings会怎样呢?

直接报错,转都转不起来。

@SafeVarargs


这种错误被称为堆污染,当把一个不带泛型的对象付给一个带泛型的变量时,往往会出现堆污染(此时系统会提示unchecked警告,而将一个有泛型的对象赋值给一个没有泛型的变量时,会给出rawtypes警告)

JAVA不支持泛型数组,因此对于形参可变的方法(形参又是泛型),更容易导致堆污染。
class ErrorUtils{public static void faultyMethod(List<String> ...lists){List [] listArray=lists;List<Integer> myList=new ArrayList<Integer>();myList.add(new Random().nextInt(100));listArray[0]=myList;String s=lists[0].get(0);}}public class ErrorUtilsTest {public static void main(String []args){ErrorUtils.faultyMethod(Arrays.asList("Hello!"),Arrays.asList("World!"));}}
输出是:
警告是:
最下面那个就是提示可能的出现堆污染。
添加一行@SafeVarargs(这是JAVA7专门为抑制堆污染警告提出的)
再看警告,只剩下两条了


@FunctionalInterface

这条注释只能修饰接口
JAVA8规定,如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),那么该接口就是函数式接口。
@FunctionalInterface就是用来指定某个接口是函数式接口。

JDK的元Annotation

JDK除了在java.lang下提供了5个基本的Annotation之外,还在java.lang.annotation包下提供了6个Meta Annotation(元Annotation),其中5个是用于修饰其它Annotation,剩下@Repeatable是JAVA8的新特性。

@Retention

其value只能是3个:
@RetentionPolicy.CLASS  编译器将其记录在class文件中,当运行JAVA程序时,JVM不可获取Annotation信息,这是默认值。
@RetentionPolicy.RUNTIME:编译器将Annotation记录在class文件中。当运行java程序时,JVM可以获取Annotation,程序可以通过反射来获取该信息。
@RetentionPolicy.SOURCE :只保留在源码中,编译器会直接抛弃这种注解

@Target

@Target只能修饰一个Annotation定义,它用于指导被修饰的Annotation可以用于修饰那些程序变元。(该成员变量的值是确定的,P647)

@Documented

@Documented用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档(所有使用该类的API文档中都会包含该Annotation说明)。

@Inherited

表明其修饰的Annotation具有继承性,如果一个类使用该Annotation,那么其子类都默认使用该Annotation。
import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic @interface Inheritable{}
然后定义一个测试的类
@Inheritableclass Base{}public class InheritedTest extends Base {public static void main(String []args){System.out.println(InheritedTest.class.isAnnotationPresent(Inheritable.class));}}
结果是true
如果去掉Inherited,结果是false


1 0