Java注解,也就是Annotation,是JAVA代码里的特殊标记,它为Java程序代码提供了一种形式化的方法,用来表达额外的某些信息,这些信息代码本身是无法表示的。我们可以方便地使用注解修饰程序元素,这里程序元素包括类、方法、成员变量等。
注解以标签的形式存在于Java代码中,注解的存在并不影响程序代码的编译和执行,它只是用来生成其他的文件或使我们在运行代码时知道被运行代码的描述信息。
使用注解时在其前面加上“@”符号,并把该注解当成一个修饰符使用,用于修饰它支持的程序元素。
注解使用的语法:
@Annotation(参数)
Annotation为注解的类型
注解的参数可以没有,也可以有一个或多个
规范:
将注解置于所有修饰符之前。
通常将注解单独放置在一行
默认情况下,注解可用于修饰任何程序元素,包括类、方法和成员变量等。
内建注解:
1.@Override注解
@Override注解被用作标注方法,它用来标识该方法是重写父类的某方法。@Override注解的用法非常简单,只要在重写的子类方法钱加上@Override即可
2.@Deprecated注解
@Deprecated注解标识已过时,如果一个程序元素被@Deprecated注解修饰,则表示此程序元素已过时,编译器将不再鼓励使用这个被标注的程序元素。如果使用,编译器则会在该程序元素上画一条斜线,表示此程序元素已过时。
3.@SuppressWarnings注解
@SuppressWarnings注解表示阻止编译器警告,被用于有选择地关闭编译器对类,方法和成员变量等程序元素及其子元素的警告。@SuppressWarnings注解会一直作用于该程序元素的所有子元素。
常用的参数如下:
deprecation:使用了过时程序元素。
unchecked:执行了未检查的转换。
unused:有程序元素未被使用。
fallthrough:switch程序块直接通往下一种情况而没有break。
path:在类路径、源文件路径等中有不存在的路径。
serial:在可序列化的类上缺少serialVersionUID定义。
finally:任何finally子句不能正常完成。
all:所有情况。
当注解类型里只有一个value成员变量,使用该注解时可以直接在注解后的括号中指定value成员变量的值。而无需使用name=value结构对的形式。在@SupperssWarnings注解类型中只有一个value成员变量,所以可以把"value="省略掉,如果@SuppressWarnings注解所声明的被禁止的警告个数只有一个时,则可不用大括号。
元注解:包含成员变量的注解类型称之为元数据注解 不包含成员变量的注解类型称
之为标记注解
@Target注解
@Target注解用于指定被其修饰的注解能用于修饰哪些程序元素(类、方法、成员变量等等),
@Target注解类型有唯一的value作为成员变量。这个成员变量java.lang.annotation.ElementType类型,ElementType类型,ElementType类型是可以被标注的程序元素的枚举类型。
ElementType.METHOD 被修饰的注解用于修饰方法
ElementType.ANNOTATION_TYPE被修饰的注解用于修饰注解
ElementType.CONSTRUCTOR 被修饰的注解用于修饰构造方法
ElementType.FIELD 被修饰的注解用于修饰成员变量
ElementType.LOCAL_VARIABLE 被修饰的注解用于修饰局部变量
ElementType.PACKAGE 被修饰的注解用于修饰包定义
ElementType.PARAMETER 被修饰的注解用于修饰参数
ElementType.TYPE 被修饰的注解用于修饰类
@Retention注解
@Retention注解:指定被修饰的注解可以保留多长时间。
RetentionPolicy.CLASS (默认值)被修饰的注解在class文件保留,java虚拟机不再保留
RetentionPolicy.RESOURCE 被修饰的注解在源文件中保留
RetentionPolicy.RUNTIME 被修饰的注解在程序运行期间被保留,编译器直接丢弃
当一个注解类型被定义为运行时注解后,该注解才是运行时可见的,当class文件
被装时被保存在class文件中的注解才会被Java虚拟机所读取。
@Document注解
指定被修饰的注解能够被JAVAdoc工具提取出来,形成文档。
@Inherited注解
注定被修饰的注解是可继承的(子类)
自定义注解
@interface 继承java.lang.annotation接口
注解的成员变量在注解类型的定义中以无参数方法的形式来声明,其方法名和
返回值分别定义了该成员变量的名字和类型。
当自定义注解带有成员变量时,使用自定义注解需要指定成员变量的值
当自定义注解的成员变量拥有默认值时,在使用当前注解时可以不指定成员
变量的值
反射
java.lang.reflect.AnnotatedElement指定了程序中可以接受注解的程序元素
class constructor field method package
使用AnnotatedElement对象的三个方法读取注解信息
getAnnotation(Class
返回存在的、指定类型的注解,如果该类型注解不存在则返回null
Annotation[] getAnnotations()
返回该程序元素上存在的所有注解
boolean isAnnotationPresent(Class extends Annotation> annotationClass)
判断该程序元素上是否包含指定类型的注解,如果存在则返回TRUE否则返回
FALSE
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
//定义两个成员变量
String name() default "JACK";
int age() default 20;
}
import java.lang.annotation.Annotation;
public class TestAnnotation {
public static void main(String[] args) {
try {
TestAnnotation t = new TestAnnotation();
t.getInfo();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
@AnnotationTest(name="张三",age=26)
public void getInfo() throws NoSuchMethodException, SecurityException{
//获取TestAnnotation对象getinfo方法里的所有注解
Annotation[] annos = TestAnnotation.class.getMethod("getInfo").getAnnotations();
//遍历annos数组
for(Annotation ann: annos){
//ann就是一个Annotation对象
//判断当前ann是否是AnnotationTest类型
if(ann instanceof AnnotationTest){
System.out.println("ann是"+ann);
//需要将ann强制转成AnnotationTest
System.out.println("ann的name是"+((AnnotationTest)ann).name());
System.out.println("ann的age是"+((AnnotationTest)ann).age());
}
}
}
}