Java 注解那些事儿

今日无事,应狒狒之邀,写一篇详细的关于注解的文章。

注解一般有如下几种作用

  • 生成文档,这是大家最常见的也是Java最早提供的注解功能。比如看源码的时候方法注释上面的 @see @param @return 等等;
  • 减少配置,可以进行运行时动态处理,得到注解信息,实现代替配置文件的功能;也可以通过插件进行编译时处理,以解决解析注解而导致的反射性能消耗;
  • 减少重复工作,比如第三方框架ButterKnife等,通过注解@BindView减少对findViewById的调用;
  • 限定作用域,例如在编译时进行格式检查,如@override 放在方法前,如果你这个同名方法并不是覆盖了超类方法,则编译时就能检查出,用注解替代枚举等等;安卓也提供了一些参数注解来限定资源参数的传入,后面我们会讲到;

注解的优点:方便,简洁,配置信息和 Java 代码放在一起,有助于增强程序的内聚性。

注解的缺点:分散到各个class文件中,所以很不方便维护,比如一些路由注解,打在activity上,尤其是支持多路径的时候,找个错能让你疯。

总体来说注解对于编码带来的好处要多于坏处的,尤其是在是恰当的使用的时候,完全可以减少或者避免他所带来的缺点的。

了解了上面这些之后我们就来看看怎么用好注解这个利器吧。

内容可能比较多,视情况分篇写。免得您看的头疼眼花从了解到放弃。

Android大部分用的Java,我们只谈Java注解和怎么自定义适合自己的注解

元注解

Java语言提供几种基本的元注解,了解并掌握它们之后我们才可以做到得心应手的自定义自己需要的注解。

Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。

  • @Target
  • @Retention
  • @Documented
  • @Inherited

@Target指定了注解对象使用范围,也就是限制了被@Target修饰的注解的可以放在什么地方上面,可以修饰:packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)

@Target取值(ElementType)有:

  • CONSTRUCTOR:用于描述构造器
  • FIELD:用于描述域
  • LOCAL_VARIABLE:用于描述局部变量
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述参数
  • TYPE:用于描述类、接口(包括注解类型) 或enum声明

比如我们见到最多的系统方法注解@Override

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

就通过@Target指定了该注解只作用于method,也就是类方法。

@Retention指定了注解对象作用的生命周期,比如有些注解是在编码阶段进行合法化检查的,只需要在源码里保留就行。无需编译进dex文件中。再比如有些注解是需要运行时通过反射获取的,就需要一直保留着。

@Retention取值(RetentionPoicy)有:

  • SOURCE:在源文件中有效
  • CLASS:在class文件中有效
  • RUNTIME:在运行时有效

我们上面的@Override例子里的@Retention(RetentionPolicy.SOURCE)就是表示@Retention(RetentionPolicy.SOURCE)注解只在源码阶段有效。

@Documented是一个标记注解,它代表着此注解会被javadoc等文档生成工具提取到文档内。在doc文档中的内容会因为此注解的信息内容不同而不同。@Documented没有属性成员。

@Inherited也是一个标记注解,它声明了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的注解类型被作用于一个class,则这个注解将被作用于该class的所有子类。

需要注意的是@Inherited注解只会被标注过的class的子类所继承。类并不会从它所实现的接口继承该注解,方法也不会从它所重载的方法继承该注解。

而且当@Inherited标注的注解的Retention属性值是RetentionPolicy.RUNTIME时,反射API会增强这种继承性。也就是说当我们使用java.lang.reflect去查询一个标注了被@Inherited修饰的注解所标注时,反射代码会去检查类和其父类,直到指定的注解类型被发现,或者到达类继承结构的顶层。

以上就是Java提供的元注解的介绍了,接下来我们看自定义注解

自定义注解

@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、类、String、enum)。可以通过default来声明参数的默认值。

使用@interface自定义注解时,会自动继承java.lang.annotation.Annotation接口,编译程序会自动完成其他细节。

定义注解时,不能继承其他的注解或接口。

自定义注解格式为

  public @interface 注解名 {定义体}

注解的参数只支持以下数据类型

  • 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上所有类型的数组

需要注意的点

  • 注解的参数只能用public或默认(default)这两个访问修饰符
  • 如果只有一个参数成员,最好把参数名称设为value后加小括号
  • 注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在(这段话抄的)

例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BindView {
    int value() default -1;
}

以上就是自定义注解的要点了。

下一篇:Android提供的常用注解以及自定义限制作用注解

下下一篇:怎么定义以及代码解析运行时注解

有什么建议的可以留言喔

如果我的博客对您有帮助,请留言鼓励下或者点个赞吧!

我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。

时间: 2024-10-10 09:24:48

Java 注解那些事儿的相关文章

Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)

如果没有用来读取注解的工具,那注解将基本没有任何作用,它也不会比注释更有用.读取注解的工具叫作注解处理器.Java提供了两种方式来处理注解:第一种是利用运行时反射机制:另一种是使用Java提供的API来处理编译期的注解. 反射机制方式的注解处理器 仅当定义的注解的@Retention为RUNTIME时,才能够通过运行时的反射机制来处理注解.下面结合例子来说明这种方式的处理方法. Java中的反射API(如java.lang.Class.java.lang.reflect.Field等)都实现了接

Java注解(1)-注解基础

注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解到底可以做什么呢? 1.注解的作用. 提供用来完整地描述程序所需要的信息,如编译期校验程序信息. 生成描述符文件,或生成新类的定义. 减轻编写"样板"代码(配置文件)的负担,可以使用注解自动生成. 更加干净易读的代码. 编译期类型检查. 2.Java提供的注解 Java5内置了一些原生的注

Java注解(3)-注解处理器(编译期|RetentionPolicy.SOURCE)

注解的处理除了可以在运行时通过反射机制处理外,还可以在编译期进行处理.在编译期处理注解时,会处理到不再产生新的源文件为止,之后再对所有源文件进行编译. Java5中提供了apt工具来进行编译期的注解处理.apt是命令行工具,与之配套的是一套描述"程序在编译时刻的静态结构"的API:Mirror API(com.sun.mirror.*).通过Mirror API可以获取到被注解的Java类型元素的信息,从而提供自定义的处理逻辑.具体的处理工具交给apt来处理.编写注解处理器的核心是两个

java注解中的元注解

一:java注解中的元注解 四个元注解分别是:@Target,@Retention,@Documented,@Inherited , 再次强调下元注解是java API提供,是专门用来定义注解的注解,其作用分别如下: @Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: ElemenetType.CONSTRUCTOR----------------------------构造器声明 ElemenetType.FIELD ----------------

Java注解

注解是一种元数据形式,提供关于不是程序部分的程序的数据.操作代码上的注解不影响注解的代码. 注解有许多用途,其中: 编译器信息 -- 注解被用于编译器检测错误或抑制警告. 编译时和部署时处理 -- 软件工具能处理注解信息生成代码.XML文件等等. 运行时处理 -- 一些注解可用在运行时检查. 1     注解基础 1.1    注解的格式 最简单的注解形式如下所示: @Entity 在符号字符(@)告诉编译器这是一个注解.在下面的例子中,注解的名称是Override: @Override voi

Java注解项目实战即模拟Hibenernate生成sql语句

整理了近期学习java注解的部分代码 ,借助java注解模拟Hibenernate ORM模型建立对象与sql语句的映射 Table 注解的创建 package com.imooc.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.

java注解例子

java注解在web框架中使用比较广泛,这使得对象之间的关系配置起来更加容易 目前web框架中最常用的两种配置对象依赖关系的方式就是注解和xml配置文件的方法,api配置相对来说用的少一些, 下面实现一个Table注解来实现数据库表和实体bean之间的对应关系,实现一个Column注解来实现数据库表中每个字段和实体bean每个属性之间的 对应关系.java中的orm基本上就是根据这种思想来实现的. Table注解代码: package com.panther.dong.annotation.an

Java注解处理器

这几天看公司一个中间件对异步的支持的新特性中,它使用注解处理器来自动生成异步接口.就看了下如何使用注解及编译期注解处理器,一下是些学习笔记吧! 此处说的Java注解及注解处理器,不是运行期注解及使用Class对象和反射来处理的处理器!而是编译期处理的源文件注解(RetentionPolicy.SOURCE);其注解处理器(Annotation Processor)是javac的一个工具,它用来在编译时扫描和处理注解(Annotation).你可以对自定义注解,并注册相应的注解处理器. 用途 编译

19.Java 注解

19.Java注解 1.Java内置注解----注解代码 @Deprecated                                    //不推荐使用的过时方法 @Deprecated public void badMethod(){ System.out.println("I am a old function"); } @Override                                        //必须是覆盖父类(接口)的函数 @Overrid