JAVA之Annotation (一)

概述

从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
{
	@Deprecated
	public 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)
@Inherited
public @interface Inheritable
{
}
然后定义一个测试的类
@Inheritable
class 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值