Annotation 注解相信大家平时经常用到,比如常见的有@Override @Deprecated @SuppressWarnings
还有很多第三方框架也用到了自定义注解,以前一直觉得很神奇,其实学习自定义才发现还是很简单的嘛
什么是注解?
由于不擅言辞,我就直接引用大神的博客介绍了,以下是大神博客地址
http://blog.csdn.net/hai_qing_xu_kong/article/details/51779695 点击打开链接
注解是一种元数据, 可以添加到java代码中. 类、方法、变量、参数、包都可以被注解,注解对注解的代码没有直接影响
首先了解下元注解,
元注解就是用来定义注解的注解.其作用就是定义注解的作用范围, 使用在什么元素上等等,
元注解共有四种@Retention, @Target, @Inherited, @Documented
@Target:
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention:
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Documented:
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
@Inherited:
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。
其中, @Retention是定义保留策略, 直接决定了我们用何种方式解析. SOUCE级别的注解是用来标记的, 比如Override, SuppressWarnings. 我们真正使用的类型是CLASS(编译时)和RUNTIME(运行时)
自定义注解:
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
以上很大一篇都是详细介绍注解的,现在直接来自定义吧
我总共创建了4个类,Person 和 PersonAttr 就是定义的注解,LaoFuzi是使用注解的类,MainActivity是运行效果的类
先看下Person
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义用于方法描述的注解
* Created by Alex on 2017/11/23.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Person {
boolean beautiful() default false;
int age() default 0;
String name() default "Alex";
}
这个注解用于方法的描述,所以用@Target({ElementType.METHOD}),保存时机一般都是用@Target({ElementType.METHOD}),因为我们绝大部分都是需要运行时用
内部定义了几个方法,后面的返回的默认值,返回值必须是可以定义常量的类型
再看下PersonAttr
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义用于成员变量描述的注解
* Created by Alex on 2017/11/23.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface PersonAttr {
String value();
}
这个注解用于描述成员变量,比如很多请求框架都用到,便于解析字段,跟Person差不多,只是@Target({ElementType.FIELD})这里改变了下,当然还可以定义其他类型
LaoFuzi,使用刚才定义的注解,方法和成员变量都用到了
public class LaoFuzi {
@PersonAttr("name")
public String name;
@Person(beautiful = false, age = 28, name = "老夫子")
public void printPersonInfo() {
}
}
最后看下效果
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Method[] methods = LaoFuzi.class.getDeclaredMethods();
for (Method method: methods) {
Person person = method.getAnnotation(Person.class);
if (person != null) {
Log.d(TAG, person.name() + " " + person.age() + " " + person.beautiful());
}
}
Field[] fields = LaoFuzi.class.getDeclaredFields();
for (Field field : fields) {
PersonAttr personAttr = field.getAnnotation(PersonAttr.class);
if (personAttr != null) {
Log.d(TAG, personAttr.value());
}
}
}
打印结果:
11-23 15:41:31.617 9793-9793/android.example.com.customannotationdemo D/MainActivity: 老夫子 28 false
11-23 15:41:31.617 9793-9793/android.example.com.customannotationdemo D/MainActivity: name
demo 地址
http://download.csdn.net/download/msn465780/10130482 点击打开链接
到这里已经完成了自定义注解,是不是很简单啊,又可以愉快的玩耍了