-
注解的概念
为Java代码提供元数据,对Java代码进行标记,配合其他技术,达到简化代码、修改逻辑、扩展功能等目的一段固定格式的标记型代码
-
注解的定义
平时我们基本上都是使用他人框架中编写好的注解来进行开发,在我们感叹这注解真**的好用的时候是不是也想过他们是咋写的呢,其实别人也是安装注解定义的常规方式去编写,把他们的想法通过代码呈现出来,实际上我们也是可以做到的(指实现自己的想法)
-
关键字
@interface
平时我们定义一个类用class,同样的我们定义一个注解就用上面这个关键字就ok了。并且,注解的本质其实就是一个继承自Annotation接口的接口,只是他特殊一些(至于他这么特殊底层是怎么实现的还没研究)。
所以,一个注解这样写就定义好了,可以拿去到处用了(拿着一边玩去~)。
public @interface HappyAnnotation { } -
元注解(圆柱姐)
就像孩子生下来要管教,注解定义之后也是要对它设置一些约束
-
@Retention
这个注解规定了注解信息能保留到哪个阶段(是的,注解不好好规定是会不见的)
取值范围固定三个
-
RetentionPolicy.SOURCE
源码中、编译期
-
RetentionPolicy.CLASS
字节码中、类加载前
-
RetentionPolicy.RUNTIME
运行中
-
-
@Target
给注解规定能作用的地方(不能啥地方都能标记上,注解满天飞了都)
取值范围固定8个
-
ElementType.TYPE
类、接口、枚举、注解(头)上
-
ElementType.FIELD
成员变量、枚举常量上
-
ElementType.METHOD
方法上
-
ElementType.PARAMETER
方法的参数上
-
ElementType.CONSTRUCTOR
构造函数上
-
ElementType.LOCAL_VARIABLE
局部变量上
-
ElementType.ANNOTATION_TYPE
注解上(跟1重叠了,更细化的控制?)
-
ElementType.PACKAGE
这个注解比较特殊,并不是注解在一般类头部包的包名上(会报错),而是注解在某个包下的package-info.java文件中的包名上,关于这个文件简单解释一下,他不是一个普通的类文件,无法通过正常创建类的方式创建,因为类名中包含“-”,需要通过创建普通file文件的方式创建,这个文件主要是用来存放一些包权限的常量和类,进行集中管理,并且可以提供包层级的注释,对这个包的功能作用等进行注释说明,并且在这个类的包名上可以进行包注解,为包注解提供便利
-
ElementType.Type_PARAMETER
泛型声明上(即尖括号内)
-
ElementType.Type_USE
到处乱七八糟能用,搞不懂
-
-
@Document
将注解中的元素包含到javadoc中去
-
@Inherited
作用在注解上,被@Inherited注解的注解在注解父类时,子类自动继承该注解,但子类可以重写该注解
-
@Repeated
作用在注解上,使被注解的注解可作用在同一个目标上多次
但这个注解用起来比较绕(那是相当滴绕啊),我们来看demo
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FruitBasket { Fruit[] value(); }@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Repeatable(FruitBasket.class) public @interface Fruit { String value(); }@Fruit("apple") @Fruit("orange") public class Person { }FruitBasket注解是用来装可重复注解Fruit注解的容器,同时也是一个注解,然后要求属性是待承装注解的一维数组
Fruit注解是我们的目标注解,用@Repeated进行注解,后面跟的属性就是刚刚我们定义的FruitBasket注解,这是一个固定的写法。然后就可以欢乐地使用了
值得注意的是我们使用反射来获取修饰Person类的时候得到的是FruitBasket注解而不是Fruit注解
public static void main(String[] args) { for (Annotation annotation : new Person().getClass().getAnnotations()) { System.out.println(annotation); } //打印输出: //@com.tthappy.annotation.FruitBasket( // value=[ // @com.tthappy.annotation.Fruit(value=apple), // @com.tthappy.annotation.Fruit(value=orange) // ] //) for (Fruit fruit : new Person().getClass().getAnnotation(FruitBasket.class).value()) { System.out.println(fruit.value()); } //打印输出: //apple //orange }
-
-
注解的属性
定义一个注解,除了需要元注解的加持,同时也需要定义属性来为注解提供足够的信息
-
属性的本质
从上文中我们知道了注解的本质其实就是一个接口,那注解的属性会是接口中的什么呢,是成员变量吗,不,注解的属性本质上是接口的方法
-
属性的定义
其实上面的例子中就包含了很多属性定义的实例
-
属性类型的约束
属性的类型是有一定约束的,只能是下面的这几种:
-
基本数据类型
-
String类型
-
枚举类型
-
Class类型
-
Annotation类型
-
以上类型的一维数组类型
-
-
-