目录
注解本身是一种标记,科学的叫法叫做“元数据”;
本身并不会对代码的运行产生任何影响,如果只使用注解本身,甚至和注释没有区别。
只有与反射合作,才能发挥出注解的作用。
Annatation(注解)是一个接口,程序可以通过反射来获取指定程序中元素的 Annotation 对象,然后通过该Annotation对象来获取注解中的元数据信息。
一、概念
1.注解
①注解:
提供一种为程序元素设置元数据的方法
②基本原则:
注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。
③注解分类:
标注注解(没有元素的注解)、单值注解、完整注解
2.元数据
①元数据:
就是关于数据的数据
②作用:
编写文档:通过代码里标识的元数据 生成文档
代码分析:通过代码里标识的元数据 对代码就行分析
编译检查:通过代码里标识的元数据 让编译器能够实现基本的编译检查
二、系统注解
1.标准注解
① @Override
保证编译时候Override函数声明的正确性
② @Deprecated
对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息
与javadoc里的@deprecated标记有相同的功能,准确的说,它还不如avadoc里的@deprecated,因为它不支持参数
③ @SuppressWarnings
作用:关闭特定的警告信息
参数:
- deprecated:使用了过时的类或方法时的警告
- unchecked:执行了未检查的转换时的警告
- fallthrough:当Switch程序块直接通往下一种情况而没有Break时的警告
- path:在类路径、源文件路径等中有不存在的路径时的警告
- serial:当在可序列化的类上缺少serialVersionUID定义时的警告
- finally:任何关于finally子句不能正常完成时的警告
- all:关于以上所有情况的警告
2.元注解
负责注解其他注解
① @Retention
作用:
表示需要在什么级别保存该注释信息
RetentionPoicy参数:
- SOURCE:注释将被编译器丢掉
- CLASS:注释在CLASS文件中可用,但会被VM丢弃,缺省
- RUNTIME:VM将在运行也保留注释,因此可以通过反射机制读取注释的信息
② @Target
作用:
该注解可以用于什么地方
ElementType参数:
- CONSTRUCTOR:构造器的声明
- FIELD:域声明(包括enum实例)
- LOCAL_VARIABLE:局部变量声明
- METHOD:方法声明
- PACKAGE:包声明
- PARAMETER:参数声明
- TYPE:类、接口(包括注解类型)或 enum声明
③ @Documented
将注释包含在JavaDoc中
④ @Inhertied
允许子类继承父类中的注释
三、注解元素数据类型
所有基本类型(int,float,boolean等)
String
Class
enum
Annotation
以上类型的数组
四、提取注解
java.lang.reflect.AnnotatedElement接口
1.已知实现类
- Class
- Construcor
- Field
- Method
- Package
2.方法
- getAnnotation:返回该程序元素上存在的指定类型的注解,如果该类型的注解不存在,则返回null
- getAnnotations:返回该程序元素上存在的所有注解
- isAnnotationPresent:判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false
- getDeclaredAnnotations:返回直接存在于此元素上的所有注解
五、注解处理器
如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中, 很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速 的构造自定义注解处理器。
六、示例
/1:*** 定义注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/**供应商编号*/
public int id() default -1;
/*** 供应商名称*/
public String name() default "";
/** * 供应商地址*/
public String address() default "";
}
//2:注解使用
public class Apple {
@FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路")
private String appleProvider;
public void setAppleProvider(String appleProvider) {
this.appleProvider = appleProvider;
}
public String getAppleProvider() {
return appleProvider;
}
}
/3:*********** 注解处理器 ***************/
public class FruitInfoUtil {
public static void getFruitInfo(Class<?> clazz) {
String strFruitProvicer = "供应商信息:";
Field[] fields = clazz.getDeclaredFields();//通过反射获取处理注解
for (Field field : fields) {
if (field.isAnnotationPresent(FruitProvider.class)) {
FruitProvider fruitProvider = (FruitProvider) field.getAnnotation(FruitProvider.class);
//注解信息的处理地方
strFruitProvicer = " 供应商编号:" + fruitProvider.id() + " 供应商名称:"
+ fruitProvider.name() + " 供应商地址:"+ fruitProvider.address();
System.out.println(strFruitProvicer);
}
}
}
}
public class FruitRun {
public static void main(String[] args) {
FruitInfoUtil.getFruitInfo(Apple.class);
/***********输出结果***************/
// 供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延
}
}