注解(Annotation)简介
Annotation(注解)是Java JDK5及其以后版本中引入的一个特性。注解是Java的一个新的类型(与接口类似),它与类、接口、枚举是在同一个层次,它们都称为Java的一个类型(TYPE)。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。它的作用非常多,进行编译检查、生成说明文档、代码分析等。
Java JDK提供的几个基本注解
1.@SuppressWarnings 该注解的作用是阻止编译器发出某些警告信息
它可以有以下参数:
deprecation 过时的类或方法的警告;
unchecked 执行了未检查的转换时的警告;
fallthrough 当swith程序块直接通往下一种情况而没有break时的警告;
path 在类路径、源文件路径等中有不存在的路径时的警告;
serial 当在可序列化的类上缺少serialVersionUID定义时的警告;
finally 任何finally子句不能完成时的警告;
all 关于以上所有情况的警告。
2.@Deprecated 该注解的作用是标记某个过时的类或方法。
3.@Override 该注解在方法前面,用来标识该方法是重写父类的某个方法。
Java JDK提供的元注解
1.@Target 它是被定义在一个注解类的前面,用来说明该注解可以被声明在哪些元素前。
它可以有以下参数:
ElementType.TYPE 说明该注解只能被声明在一个类前;
ElementType.FIELD 说明该注解只能被声明在一个类的字段前;
ElementType.METHOD 说明该注解只能被声明在一个类的方法前;
ElementType.PARAMETER 说明该注解只能被声明在一个方法参数前;
ElementType.CONSTRUCTOR 说明该注解只能声明在一个类的构造方法前;
ElementType.LOCAL_VARIABLE 说明该注解只能声明在一个局部变量前;
ElementType.ANNOTATION_TYPE 说明该注解只能声明在一个注解类型前;
ElementType.PACKAGE 说明该注解只能声明在一个包名前。
2.@Retention 它是被定义在一个注解类的前面,用来说明该注解的声明周期。
它可以有一下参数:
RetentionPolicy.SOURCE 指定注解只保留在一个源文件当中;
RetentionPolicy.CLASS 指定注解只保留在一个class文件中;
RetentionPolicy.RUNTIME 指定注解可以保留在程序运行期间。
3.@Documented 用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
4.@Inherited 阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
注解的声明周期
一个注解可以有三个不同的声明周期,它的默认声明周期是保留在一个class文件,我们可以使用@Retention元注解指定它的生命周期。
1.java文件 当在一个注解类前定义了@Retention(RetentionPolicy.SOURCE)的注解,那么说明该注解只保留在一个源文件当中,当编译器将源文件编译成class文件时,它不会将源文件中定义的注解保留在class文件中。
2.class文件 当在一个注解类前定义了@Retention(RetentionPolicy.CLASS)的注解,那么说明该注解只保留在一个class文件当中,当加载class文件到内存时,虚拟机会将注解去掉,从而程序中不能访问。
3.程序运行期间 当在一个注解类前定义了@Retention(RetentionPolicy.RUNTIME)的注解,说明该注解在程序运行期间都会在驻留内存当中。因此,我们可以通过反射来获得定义在某个类上的所有注解。
自定义注解
格式如下:
public @interface myAnno {
//定义公共的final静态属性
...
//定义公共的抽象方法
}
1.注解和接口类似,它只能定义final静态属性和公共抽象方法。
2.注解的方法:
方法前默认会加上public abstract。
在声明方法时可以定义方法的默认返回值。例如String color() default "Blue"; 。
方法的返回值可以为8中基本类型,String、Class、枚举、注解以及这些类型的数组。
下面来看一个实例:
定义注解:
package com.tzy.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Description {
String value();
}
使用注解:
package com.tzy.annotation;
@Description("People has name and gender.")
public class People {
private String name;
private String gender;
public People(String name, String gender) {
this.name = name;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
得到注解:
package com.tzy.annotation;
public class AnnotationDemo {
public static void main(String[] args) {
String className = "com.tzy.annotation.People";
try {
Class<?> annoDemo = Class.forName(className);
if (annoDemo.isAnnotationPresent(Description.class)) {
Description description = (Description) annoDemo.getAnnotation(Description.class);
System.out.println(description.value());
}
} catch (ClassNotFoundException e) {
System.err.println(e);
}
}
}
运行结果如下:
People has name and gender.
总结
注解可以看成是一个接口,注解实例就是一个实现了该接口的动态代理。注解大多是用来对某个类、方法、字段进行说明标识的,以便在程序运行期间我们通过反射获得该字段或方法的注解的实例,来决定该做什么处理或者不该做什么处理。