基本Annotation
Java提供了三个基本Annotaion
@Override
@Deprecated
@SuppressWarnings
限定重写父类方法:@Override
@Override起到验证作用,被@Override修饰的方法是不是重写了父类方法,如果不是则报异常
/**
注解
*/
class Fruit
{
public void foo()
{
System.out.println("水果的info方法...");
}
}
class Apple extends Fruit
{
//使用@Override指定下面方法必须重写父类方法
@Override
public void foo()
{
System.out.println("苹果重写水果的info方法...");
}
}
标记已过时:@Deprecated
@Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告
/**
注解
*/
class Apple
{
//定义info方法已过时
@Deprecated
public void info()
{
System.out.println("Apple的info方法");
}
}
class DeprecatedTest
{
public static void main(String[] args)
{
//下面使用info方法时将会被编译器警告
new Apple().info();
}
}
抑制编译器警告:@SuppressWarnings
@SuppressWarnings指示被Annotation标识的程序元素(以及在该程序元素中的所有子元素)取消显示指定的编译器警告。@SuppressWarnings会一直作用于该程序元素的所有子元素
/**
注解
*/
//关闭整个类里的编译器警告
@SuppressWarnings(value = "unchecked")
class SuppressWarningsTest
{
public static void main(String[] args)
{
//将不会有警告
List<String> myList = new ArrayList();
}
}
自定义Annotation
定义新的Annotation类型使用@interface关键字(在原有的interface关键字前增加@符号),自定义注解默认继承Annotation接口
/**
自定义注解
*/
public @interface MyTag
{
//定义成员变量,形式类似抽象方法
String name();
int age();
//为成员变量指定默认值
String address() default "北京";
}
可以把元数据分为两类:
标记Annotation:一个没有成员定义的Annotation类型被称为标记,这种Annotation仅使用自身的存在与否来为我们提供信息
元数据Annotation:那些包含成员变量的Annotation
元注解(Meta Annotation)
JDK除了在java.lang下提供了3个基本Annotation之外,还在java.lang.annotation包下提供了4个Meta Annotation(元Annotation),这4个Annotation都是用于修饰其他Annotation定义
使用@Retention
@Retention用于修饰Annotation定义,用于指定该Annotation可以保存多长时间,@Retention包含一个RetentionPolicy枚举实例的变量,所以使用@Retention必须为该成员变量指定值
RetentionPolicy的实例有如下三个:
RetentionPolicy.SOURCE //不编译进class文件
RetentionPolicy.CLASS //编译器将把注解记录在class文件中,当运行Java程序时,JVM不再保留注解。这是默认值
RetentionPolicy.RUNTIME //注解记录在class文件中,JVM也会保留注解,程序可以通过反射获取注解
//定义下面的Testable Annotation保留到运行时
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Testable{}
//或用如下的写法
//当Annotation的成员变量名为value时,可以在括号中直接指定值
@Retention(RetentionPolicy.RUNTIME)
public @interface Testable{}
使用@Target
用于修饰Annotation的定义,指定被修饰的Annotation能用于修饰哪些程序元素
@Target Annotation也包含一个名为value的ElementType枚举实例:
ElementType.TYPE //可以修饰类、接口(包括注解类型)或枚举定义
ElementType.ANNOTATION_TYPE //指定只能修饰Annotation
ElementType.CONSTRUCTOR //只能修饰构造器
ElementType.FIELD //只能修饰成员变量
ElementType.LOCAL_VARIABLE //只能修饰局部变量
ElementType.METHOD //只能修饰方法
ElementType.PACKAGE //只能修饰包定义
/**
元Annotation,@Target
*/
@Target(ElementType.FIELD)
public @interface Demo
{
}
//接收的参数可以是一个数组
@Target({ElementType.Type, ElementType.Method})
public @interface Demo2
{
}
使用@Documented
@Documented用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//定义Testable Annotation将被javadoc工具提取
@Documented
public @interface Testable
{
}
使用@Inherited
@Inherited元Annotation指定被它修饰的Annotation将具有继承性
如果某个类使用了一个Test Annotation(定义该Annotation时使用了@inherited修饰)修饰,则其子类将自动具有Test注解
反射提取Annotation的信息
当一个Annotation类型被定义为运行时Annotation后,注解运行时才可见,只有通过反射才可以读取运行时Annotation
Class、Constructor、Field、Method、Package均实现了AnnotatedElement接口,实现了如下方法:
T getAnnotation(Class<T> annotationClass) //返回该程序元素上存在的,指定类型的注解,如果该类型不存在,则返回null
Annotation[] getAnnotations() //返回该程序元素上存在的所有注解
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) //判断该程序元素上是否包含指定类型的注解
import java.lang.annotation.*;
/**
使用反射获取Annotation,必须保证要获取的注解是运行时注解
*/
//设置MyAnnotation为运行时注解
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation
{
//定义成员
String color();
//带默认值的成员
int num() default 23;
//数组成员
int[] arr();
//枚举成员
EnumTest enumAttribute() default EnumTest.Red;
//注解成员
anotherAnnotation anotherAnn() default @anotherAnnotation(age = 999);
}
@MyAnnotation(color = "Red", arr = {2, 3, 5, 5})
class AnnotationTest
{
public static void main(String[] args)
{
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class))
{
MyAnnotation annotation = AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation.color());
System.out.println(annotation.arr().length);
System.out.println(annotation.enumAttribute().nextLamp().name());
System.out.println(annotation.anotherAnn().age());
}
}
}
//定义一个枚举
enum EnumTest
{
Red(30)
{
public EnumTest nextLamp()
{
return Green;
}
},
Green(45)
{
public EnumTest nextLamp()
{
return Yellow;
}
},
Yellow(5)
{
public EnumTest nextLamp()
{
return Red;
}
};
private int num = 0;
//构造函数只能使用private,默认使用的就是private
private EnumTest(int num)
{
this.num = num;
}
//抽象方法
public abstract EnumTest nextLamp();
}
//定义一个注解
@interface anotherAnnotation
{
int age();
}
---------------------- ASP.Net+Android+IOS开发</a>、 .Net培训、期待与您交流! ----------------------