目录
- 概念
- 分类
- 按照来源分类
- 按照作用分类
- JDK注解
- 使用JDK注解示例
- 自定义注解
- 自定义注解格式
- 注解中抽象方法约束
- 自定义注解的本质
- 元注解
- @Target
- @Retention
- @Documented
- @Inherited
- 完整的自定义注解示例
概念
注解(Annotation)
,也叫元数据
。一种代码级别的说明。它是JDK1.5
及以后版本引入的一个特性,与类、接口、枚举是在同一个层次
。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
分类
按照来源分类
-
JDK注解
:如@Override、@Deprecated、@SuppressWarnings。 -
第三方注解
:如Spring中定义了许多注解:@Autowried、@Controller、@Service、@Repository。 -
自定义注解
:我们也可以自己定义注解,下面会介绍。
按照作用分类
-
编写文档
:通过代码里标识的注解生成Java doc文档。 -
编译检查
:通过代码里标识的注解让编译器能够实现基本的编译检查。如:@Override
注解在编译时检查方法是否是重写父类(或实现的接口)中的方法。 -
代码分析
:通过代码里标识的注解对代码进行分析。如:通过反射机制
可以获取方法或类上的注解,从而执行进一步操作。还常用来代替配置
。
JDK注解
- @Override:检测被该注解标注的方法是否是继承自父类(接口)的。
- @Deprecated:该注解标注的内容,表示已过时。
- @SuppressWarnings:关闭警告信息的显示。
使用JDK注解示例
package com.zys.hello.annotation;
/**
* @program hello-annotation
* @description Jdk内置注解使用
* @author Leo
* @create 2019-09-04 14:59
**/
@SuppressWarnings("all")
public class JdkAnnotationTest {
/**
* Override注解:编译时检查次方法是否为复写父类中的方法,如果不是则编译报错
* @return
*/
@Override
public String toString() {
return super.toString();
}
/**
* Deprecated注解:表明该方法不推荐使用,但仍可以使用,使用时会有删除线
*/
@Deprecated
public void method(){
//有缺陷的方法,不推荐使用
}
/**
* 关闭警告,一般传递all参数表示关闭所有警告,可以作用在方法和类上。
*/
@SuppressWarnings("all")
public void create(){
}
}
自定义注解
自定义注解格式
元注解
public @interface 注解名称{
方法列表;
}
如:
@Documented
public @interface MyAnnotation{
String value1();
int value2();
}
注解中抽象方法约束
说明
:接口中的抽象方法通常称为属性
,因为在使用时很像是在给属性赋值。下面多处会使用属性指代注解中定义的抽象方法。
一、 注解中的抽象方法必须有返回值
。且返回值类型有一下几种:
- 基本数据类型。如:int、float、long等。
- String类型。
- 枚举类型。
- 注解类型。
- 以上类型的数组形式。如:int[]、String[]等。
二、如果在注解中定义了属性,那么在使用时就需要遵循以下几条规则:
- 如果定义属性时,使用
default
关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。 - 如果只有一个属性需要赋值,并且属性的名称是
value
,则value可以省略
,直接定义值即可。 - 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略。
自定义注解的本质
注解本质上就是一个接口
,该接口默认继承Annotation接口
。如我们上面自定义的注解经过编译反编译的代码为:
public interface MyAnnotation extends java.lang.annotation.Annotation {
public abstract String value1();
public abstract int value2();
}
元注解
可以认为元注解
是用于描述注解的注解。有以下几个:
@Target
@Target:描述注解能够作用的位置。接收ElementType
枚举类型。如:
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotation {
}
ElementType.TYPE
:表示可以在类
上使用。ElementType.FIELD
:表示可以在字段
上使用。ElementType.METHOD
:表示可以在方法
上使用。
还有很多就不一一列举,可以查阅API文档。
@Retention
@Retention:描述注解被保留的阶段。接收RetentionPolicy
枚举类型。如:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
RetentionPolicy.RUNTIME
:表示保留到运行时
阶段(最常使用),JVM加载CLASS文件时会加载该注解。RetentionPolicy.CLASS
:表示保留到字节码
阶段,该注解编译时会编译到CLASS文件中, 但是JVM加载CLASS文件时会舍弃。RetentionPolicy.SOURCE
:表示保留到源码
阶段,该注解只会存在源码文件中, 编译时会舍弃。
@Documented
@Documented:描述注解是否被抽取到API文档中。加了就表示生成API文档时该注解会被提取进去,否则不会。
@Inherited
@Inherited:描述注解是否被子类继承。加了就表示该注解可以被子类继承,否则不能被继承。
完整的自定义注解示例
完整的自定义注解:
package com.zys.hello.annotation;
import java.lang.annotation.*;
/**
* @author Leo
* @program hello-annotation
* @description 自定义注解
* @create 2019-09-04 15:12
**/
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
//字符串类型
String name();
//基本数据类型,有默认值,在使用时可以不赋值
int age() default 18;
//枚举类型
PersonEnum person();
//注解类型
MyAnnotation2 annotation();
//数组类型
String[] values();
}
空的自定义注解(演示作为注解中的属性类型):
package com.zys.hello.annotation;
/**
* @author Leo
* @program hello-annotation
* @description
* @create 2019-09-04 15:34
**/
public @interface MyAnnotation2 {
}
枚举类型(演示作为注解中的属性类型):
package com.zys.hello.annotation;
/**
* @author Leo
* @program hello-annotation
* @description
* @create 2019-09-04 15:36
**/
public enum PersonEnum {
P1,P2
}
使用自定义注解演示:
package com.zys.hello.annotation;
/**
* @author Leo
* @program hello-annotation
* @description 使用自定义属性
* @create 2019-09-04 15:25
**/
public class AnnotationConsumer {
@MyAnnotation(name = "张三", person = PersonEnum.P1, annotation = @MyAnnotation2, values = {"val1","val2","val3"})
public void method(){
}
}