java 学习自定义注解Annotation
2017-11-23 18:47
232 查看
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
这个注解用于方法的描述,所以用@Target({ElementType.METHOD}),保存时机一般都是用@Target({ElementType.METHOD}),因为我们绝大部分都是需要运行时用
内部定义了几个方法,后面的返回的默认值,返回值必须是可以定义常量的类型
再看下PersonAttr
这个注解用于描述成员变量,比如很多请求框架都用到,便于解析字段,跟Person差不多,只是@Target({ElementType.FIELD})这里改变了下,当然还可以定义其他类型
LaoFuzi,使用刚才定义的注解,方法和成员变量都用到了
最后看下效果
打印结果:
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 点击打开链接
到这里已经完成了自定义注解,是不是很简单啊,又可以愉快的玩耍了
还有很多第三方框架也用到了自定义注解,以前一直觉得很神奇,其实学习自定义才发现还是很简单的嘛
什么是注解?
由于不擅言辞,我就直接引用大神的博客介绍了,以下是大神博客地址
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 点击打开链接
到这里已经完成了自定义注解,是不是很简单啊,又可以愉快的玩耍了
相关文章推荐
- java annotation注解学习,自定义注解
- Java 学习笔记05:Spring 基于注解(Annotation)的IOC
- Java基础-学习使用Annotation注解对象
- Java基础-学习使用Annotation注解对象
- Java注解annotation用法和自定义注解处理器
- Java 学习笔记06:Spring 基于注解(Annotation)的AOP
- Java注解应用实例 - Annotation, 自定义注解, 注解类规则
- 深入理解Java:注解(Annotation)自定义注解入门(转载)
- Java 自定义注解(Annotation)
- Java注解annotation用法和自定义注解处理器
- 深入理解Java:注解(Annotation)自定义注解入门
- java学习笔记(annotation 注解_1)
- Java Annotation自定义注解详解
- java注解应用实例 - Annotation, 自定义注解, 注解类规则
- Java自定义注解Annotation的使用
- 深入理解Java:注解(Annotation)自定义注解入门
- Java Annotation自定义注解详解
- java 之 注解Annotation学习示例
- java自定义注解,annotation
- java注解应用实例 - Annotation, 自定义注解, 注解类规则