@interface
@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。
方法的名称就是参数的名称,返回值类型就是参数的类型
参数类型只能是基本类型、Class、String、enum。
可以通过default来声明参数的默认值。
Java注解就是一种特殊的接口,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,因此在自定义注解时不能继承其他的注解或者接口。
注解的应用
- 生成文档。如@param @return 等
- 替代配置文件功能。如spring2.5开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量
- 在编译时进行格式检查。如@Override
自定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ProductAnnotation {
//类型枚举
public enum Type{ 手机,电脑,平板};
//商品类型
Type productType() default Type.手机;
//商品发布时间
String publishYear() default "";
//商品名称
String productName() default "";
}
Target 指明该类型的注解可以注解的元素范围,主要包括以下几种参数类型:
ElementType.TYPE 用于类,接口,枚举,但不能是注解
ElementType.FIELD 作用于字段,包含枚举值
ElementType.METHOD 作用于方法,不包含构造方法
ElementType.PARAMETER 作用于方法的参数
ElementType.CONSTRUCTOR 作用于构造方法
ElementType.LOCAL_VERIABLE 作用于本地变量或者catch语句
ElementType.ANNOTATION_TYPE 作用于注解
ElementType.PACKAGE 作用于包
Retention 指明在什么级别显示此注解,主要包括以下几种参数类型:
RetentionPolicy.SOURCE 注解存在于源代码中,编译时会被抛弃
RetentionPolicy.CLASS 注解会被编译到class文件中,但是JVM会忽略
RetentionPolicy.RUNTIME JVM会读取注解,同时会保存到class文件中
通过反射获取注解属性值
注解的解析依赖于反射。jdk1.5 增加了注解,也增加了读取注解的api,在java.lang.reflect包中新增了AnnotatedElement接口,JDK源码如下:
public interface AnnotatedElement {
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
Annotation[] getAnnotations();
Annotation[] getDeclaredAnnotations();
}
isAnnotationPresent:判断是否标注了指定注解
getAnnotation:获取指定注解,没有则返回null
getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组
通过反射获取注解属性值的例子:
public class ProductReflectAnnotation {
@ProductAnnotation(productName="iphone X",publishYear="2017发布")
private String iphoneX;//iponeX配上注解
@ProductAnnotation(productType= ProductAnnotation.Type.电脑,productName="mac",publishYear="2018发布")
private String mac;//Mac配上注解
private String noAnnotationField;//noAnnotationField不加注解
public static void main(String[] args) {
// 解析ProductReflectAnnotation类属性的注解
// getDeclaredFields方法会返回ProductReflectAnnotation类所有的属性
Field[] fields = ProductReflectAnnotation.class.getDeclaredFields();
for(Field field : fields){
//判断属性是否标注了@ProductAnnotation注解
boolean fieldHasAnno = field.isAnnotationPresent(ProductAnnotation.class);
if(fieldHasAnno){
//获取@ProductAnnotation注解
ProductAnnotation product = field.getAnnotation(ProductAnnotation.class);
//获取@ProductAnnotation注解 参数值
String name = product.productName();
String publishYear = product.publishYear();
ProductAnnotation.Type type = product.productType();
System.out.println("[" + field.getName() + "] " + name + ","+ type + "," + publishYear);
}
}
}
}
输出:
[iphoneX] iphone X,手机,2017发布
[mac] mac,电脑,2018发布