重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
注解:
注解为我们在代码中添加信息提供一种形式化的方法,使我们可以在源码、编译时、运行时非常方便的使用这些数据。
创新互联专注于中大型企业的成都网站建设、网站制作和网站改版、网站营销服务,追求商业策划与数据分析、创意艺术与技术开发的融合,累计客户千余家,服务满意度达97%。帮助广大客户顺利对接上互联网浪潮,准确优选出符合自己需要的互联网运用,我们将一直专注成都品牌网站建设和互联网程序开发,在前进的路上,与客户一起成长!
注解是在JAVA SE5中引入的,注解让代码更干净易读并且可以实现编译期类型检查等。当创建描述性质的类或接口时,如果有重复性的工作,就可以考虑使用注解来简化或自动化该过程。我们可以让注解保存在源代码中,并且利用Annotation API处理注解,得到我们想要的数据并加以处理,注解的使用比较简单,JAVA SE5内置了3种:
先来看内置注解@Override是怎么被定义的,它位于package java.lang之下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Target、@Retention称为元注解:元注解负责注解其他的注释,如:@Target定义声明的注解的作用域(作用在类上还是方法上)
br/>@Target定义声明的注解的作用域(作用在类上还是方法上)
除了@Target、@Retention还有@Documented及@Inherited,下面用一个表格来分别列出他们各自的作用:
首先来自定义一个注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationInfo {
String[] value();
int requestCode() default 0;
}
@Target(ElementType.METHOD)指明了我们的注解是作用在方法上的
@Retention(RetentionPolicy.RUNTIME)表示注解在程序运行时期也会存在,即注解信息也会加载到虚拟机VM中,所以可以通过反射来获取注解的相关信息:
public class AnnotationExample {
/**
* 注解模拟请求权限
*/
@AnnotationInfo(value = {"android.permission.CALL_PHONE", "android.permission.CAMERA"}, requestCode = 10)
public void requestPermission() {
//其他逻辑
}
}
接着来编写一个运行时解析注解的Java类:AnnotationRuntimeProcessor.java
public class AnnotationRuntimeProcessor {
public static void main(String[] args) {
try {
//获取AnnotationExample的Class对象
Class> cls = Class.forName("com.javastudy.Annotation.AnnotationExample");
//获取AnnotationExample类中的方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
//过滤不含自定义注解AnnotationInfo的方法
boolean isHasAnnotation = method.isAnnotationPresent(AnnotationInfo.class);
if (isHasAnnotation) {
method.setAccessible(true);
//获取方法上的注解
AnnotationInfo aInfo = method.getAnnotation(AnnotationInfo.class);
if (aInfo == null) return;
//解析注解上对应的信息
String[] permissions = aInfo.value();
System.out.println("value: " + Arrays.toString(permissions));
int requestCode = aInfo.requestCode();
System.out.println("requestCode: " + requestCode);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的逻辑很简单,反射拿到有注解对应类的Class对象,筛选含有注解的方法,最后获取方法上的注解并解析,运行结果如下:
value: [android.permission.CALL_PHONE, android.permission.CAMERA]
requestCode: 10
AbstractProcessor是javax下的API,java和javax都是Java的API(Application Programming Interface)包,java是核心包,javax的x是extension的意思,也就是扩展包。一般继承AbstractProcessor需要实现下面的几个方法:
public class ProcessorExample extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
//processingEnvironment提供各种工具类 如Elements Filer Types SourceVersion等
super.init(processingEnvironment);
}
/**
* 扫描 评估和处理注解代码 生成Java代码
*
* @param set 注解类型
* @param roundEnvironment 有关当前和以前的信息环境 查询出包含特定注解的被注解元素
* @return 返回true 表示注解已声明 后续Processor不会再处理 false表示后续Processor会处理他们
*/
@Override
public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
return false;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return super.getSupportedSourceVersion();
}
@Override
public Set getSupportedAnnotationTypes() {
return super.getSupportedAnnotationTypes();
}
}