天天看点

Java自定义注解[一]

1:注解【Annotation】是JDK1.5之后新增的重要特性,通过注解,程序开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息。

Annotation可以用来修饰类,属性,方法,而且Annotation不影响程序的运行,无论是否使用Annotation代码都可以正常的执行。

java.lang.annotation.Annotation是Annotation的接口,只要是Annotation都必须实现此接口,其定义如下:

public abstract interface Annotation {
    // 返回此Annotation的注释类型
    public abstract Class<? extends Annotation> annotationType();

    public abstract boolean equals(java.lang.Object arg0);

    public abstract int hashCode();

    public abstract java.lang.String toString();
}
           

2:JDK5之后,系统内建了3个Annotation类型,用户直接使用即可。

         @Override:覆写的Annotation
	 @Deprecated:不赞成使用的Annotation
	 @SuppressWarnings:压制安全警告的Annotation
           

2.1:@Override主要在方法覆写时使用,用于确保方法覆写的正确性。如下所示:

// 父类Person
class Person {
	protected String name;
	public Person(String name) {
		super();
		this.name = name;
	}
	public String getInfo1() {
		return "这是父类Person,名字是:" + name;
	}
	public String getInfo2() {
		return "这是父类Person,名字是:" + name;
	}
}
           
Java自定义注解[一]

可以发现,使用@Override注解后,错误的方法覆写会给出提示,所以,使用@Override注解可以确保方法被正确覆写。

@Override只能使用在方法上,而其他元素,包括类,属性上是不能使用的。

2.2:@Deprecated注释的主要功能是用来声明一个不建议使用的方法或类或属性等,如果在程序中使用了此注解,则会在编译时出现警告信息。依然以Person类为例:

Java自定义注解[一]

虽然有警告信息,但是程序依然可以正常执行,只是不建议使用,并不是不能使用。依然使用Student类继承Person类:

Java自定义注解[一]

可以发现父类Person会有警告提示,但方法的警告并未被继承下来

Java自定义注解[一]

补充:警告不建议使用的方法有很多,比如Thread类中的suspend(),stop(),resume()三个方法不建议使用,实际上就是使用了@Deprecated注释声明的。

2.3:@SuppressWarnings注释主要是用于压制警告,当程序产生警告,但警告并不影响程序正确执行时,就可以使用@SuppressWarnings注解,这样可以让代码看起来洁净。

比如在声明集合时没有指定泛型:

Java自定义注解[一]

这里出现了两个警告,它们代表的含义并不相同:

Java自定义注解[一]

rawtypes 是指传参时也要传递带泛型的参数;unused  是指定义的变量在代码中并未使用且无法访问

我们发现@SuppressWarnings注解可以同时传递多个参数,是按照数据的格式操作的。

public static void main(String[] args) {
		@SuppressWarnings(value={ "rawtypes", "unused" })
		List list = new ArrayList<String>();
	}
           

在设置注解的时候,是以"key-value”的形式出现的。

以上简要的介绍了注解的使用及其作用。

接下来,我们来了解注解的声明

3:元注解

元注解是指注解的注解。包括 @Target, @Retention,@Document ,@Inherited四种

3.1:@Target 注解

一个Annotation如果没有明确的指明定义的位置,则可以再任何地方使用。如果希望一个自定义的注解只能再指定的位置出现,例如像@Override只能出现在方法上,则必须使用@Target注释。以@Override为例:

@java.lang.annotation.Target(value={java.lang.annotation.ElementType.METHOD})
@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)
public abstract @interface java.lang.Override extends java.lang.annotation.Annotation {

}
           

可以发现,@Override的声明范围为METHOD,所以它只能出现在方法上,而不能出现在其他地方,否则会报错

Java自定义注解[一]

如图所示,当@Override出现在类上时,会报错。

@Target的范围为:

@Target(ElementType.TYPE)   //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR)  //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包 
           

3.2:@Retention注解

@Retention用于声明注解的保留位置,有三个取值

@Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到  
           

将注解声明为在程序执行时起作用是一种比较常见的使用方法,而如果设置为其他范围,则以后再Annotation的应用中肯定是无法访问到的。

3.3:@Document注解

任何一个自定义的Annotation实际上多上都是通过@Document进行注释的。指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用@Document进行注解,这种类型的注解被作为被标注的程序成员的公共API。

3.4:@Inherited注解

用于标识一个父类的注解是否可以被子类所继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。

------未完待续.......................