- 生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等
- 跟踪代码依赖性,实现替代配置文件功能,替代xml的作用,SpringMVC中比较多少使用。
- 在编译时进行格式检查,如 @Overrider @CallSuper @Nullable 和 @NonNull等
- Android中常见用法 1)以及资源注解@LayoutRes、@IntegerRes, @StringRes、@ColorRes等 2)权限注解@RequiresPermission 3)进程类注解@UiThread,@BinderThread,@MainThread,@WorkerThread 4)ButterKnife 、EventBus、Dagger2框架
元注解:
那么注解是怎么定义的呢,我们首先看下常用的Override 注解。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
这里就涉及到元注解,我们一般用元注解来定义注解,元注解主要有以下几个。下面我们会一一进行介绍。
- @Target
- @Retention
- @Documented
- @Inherited
- @Reptable JAVA8(新增)
@Target
描述注解的使用范围(即:被修饰的注解可以用在什么地方)。主要为以下类型:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
- Type parameter declaration
- @since 1.8
*/
TYPE_PARAMETER,
/**
- Use of a type
- @since 1.8
*/
TYPE_USE
}
@Documented
描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。
@Inherited
Inherited注解的作用是:使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。
@Retention
Retention注解取值都在RetentionPolicy中
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
- SOURCE:在源文件中有效(即源文件保留), @Override, @SuppressWarnings都属于这类注解;
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
RetentionPolicy.Source
我们来看下RetentionPolicy.Source 的使用场景:由于在编译的过程中这个注解还被保留着,所以在编译过程中可以针对这个policy进行一些操作。
- 枚举类型
有时候我们会使用Enum来定义枚举,对于枚举来说占用的内存往往是使用静态常量的两倍,但是我们更推荐用注解定义枚举类型。 使用方式如下:
@IntDef({Color.RED , Color.YELLOW ,Color.BLUE})
@Retention(RetentionPolicy.SOURCE)
public @interface Color{
int RED = 1;
int YELLOW = 2;
int BLUE= 3;
}
- lombok类似场景
还有一种场景是比如在自动生成java代码的场景下使用。最常见的就是lombok的使用了,可以自动生成field的get和set方法以及toString方法,构造器等 详细实现方式及原理见:www.jianshu.com/p/fc06578e8…
RetentionPolicy.Class
CLASS:在class文件中有效(即class保留)。 编译时注解注解处理器的实现主要依赖于AbstractProcessor来实现,这个类是在javax.annotation.processing包中,同时为了我们自己生成java源文件方便,我们还需要引入一些第三方库,主要包括 javapoet 用于生成java源文件,可参考github.com/square/java… auto-service 主要用于生成一些辅助信息,例如META-INF/services 一些信息等. 典型案例框架:Butterknife 基本原理如下:
注解处理器
首先来了解下什么是注解处理器,注解处理器是javac的一个工具,它用来在编译时扫描和处理注解(Annotation)。 你可以自定义注解,并注册到相应的注解处理器,由注解处理器来处理你的注解。一个注解的注解处理器,以java代码(或者编译过的字节码)作为输入,生成文件(通常是.java文件)作为输出。这些生成的Java代码是在生成的.java文件中,所以你不能修改已经存在的Java类,例如向已有的类中添加方法。这些生成的Java文件,会同其他普通的手动编写的Java源代码一样被javac编译。
自定义RetentionPolicy.Class 注解场景
这里仅介绍AbstractProcessor相关接口,后续后做自定义注解的说明。
public class MyProcessor extends AbstractProcessor {
private Elements mElementsUtils;
/**
- 注解初始化接口,一般用于做一些初始化准备操作;
-
- processingEnvironment 提供了一些工具
- 包括操作元素、打印信息、文件管理器以及其他工具
- @param processingEnvironment
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
// 元素操作工具
Elements elementUtils = processingEnvironment.getElementUtils();
mElementsUtils = elementUtils;
// 用于创建java源文件或者class文件
Filer filer = processingEnvironment.getFiler();
// 区域信息
Locale locale = processingEnvironment.getLocale();
// 传递给注释处理工具的特定于处理器的选项
Map<String, String> options = processingEnvironment.getOptions();
//任何生成的 source和 class文件应符合的源版本
SourceVersion sourceVersion = processingEnvironment.getSourceVersion();
//一些用于对类型进行操作的实用程序方法的实现
Types typeUtils = processingEnvironment.getTypeUtils();
//返回用于报告错误,警告和其他通知的消息。
Messager messager = processingEnvironment.getMessager();
}
/**
- 注解处理接口,注解真正实现的逻辑
- 我们可以通过JavaPoet 生成java源文件
- @param annotations 请求处理的注释类型
- @param roundEnvironment 有关当前和上一轮信息的环境
- @return 如果返回true, 声明注释类型,并且不会要求后续处理器处理它们; 如果返回false ,则注释类型无人认领,可能会要求后续处理器处理它们
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
//如果在前一轮处理中引发错误,则返回true ; 否则返回false
boolean b = roundEnvironment.errorRaised();
// 返回前一轮生成的注释处理的root elements
Set<? extends Element> rootElements = roundEnvironment.getRootElements();
//如果此轮生成的类型不受后续轮注释处理的影响,则返回true ; 否则返回false 。
boolean b1 = roundEnvironment.processingOver();
// 返回使用给定注释类型注释的元素。
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(MyAnnotations.class);
for (Element element : elements) {
TypeElement typeElement = (TypeElement) element;
//获取注解的值
MyAnnotations annotation = typeElement.getAnnotation(MyAnnotations.class);
int value = annotation.value();
//获取此类型元素的完全限定名称
String s = typeElement.getQualifiedName().toString();
//获取当前注解的包路径
PackageElement packageElement = mElementsUtils.getPackageOf(typeElement);
String packageName = packageElement.getQualifiedName().toString();
}
return true;
}
/**
- 此处理器支持的注释类型的名称
- @return
*/
@Override
public Set getSupportedAnnotationTypes() {
// 本处理器仅处理MyAnnotations的注解
Set supportedAnnotationTypes = new HashSet<>();
supportedAnnotationTypes.add(MyAnnotations.class.getCanonicalName());
return supportedAnnotationTypes;
}
/**
- 返回此注释处理器支持的最新源版本
- @return
*/
@Override
public SourceVersion getSupportedSourceVersion() {
return super.getSupportedSourceVersion();
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-DEDhZKuY-1711995077377)]