注解
1、概述
1.1 定义
注解(Annotation),是jdk5.0引入的技术,用它可以对java中的某一个段程序进行说明或标注,并且这个注解的信息可以被其他程序使用特定的方式读取到,从而完成相应的操作。
例如,重写时的注解@Override
1.2 注解与注释的区别
(1)注释是** 给程序员看**的,无论怎么设置,编译后class文件中都是【没有】注释信息,方便程序员快速了解代码的作用或结构
(2)注解是给其他程序看的,通过参数的设置,可以在编译后class文件中【保留】注解的信息,其他程序读取后,可以完成特定的操作
2、格式
没有属性的注解
public @interface 注解名称{
}
有属性但没有默认值的注解
public @interface 注解名称{
public 属性类型 属性名();
}
有属性且有默认值的注解
public @interface 注解名称{
属性类型 属性名() default 默认值;
}
可以看到注解都是interface接口;public 可以省去不写,默认就是public
3、注解使用范围
(1)TYPE,使用在类,接口、注解,枚举等类型上面
@Test
public class Hello{
}
(2)FIELD,使用在属性上面
public class Hello{
@Test
private String msg;
}
(3)METHOD,使用在方法上面
public class Hello{
@Test
public void say(){}
}
(4)PARAMETER,使用在方法的参数前面
public class Hello{
public void say(@Test String name){
}
}
(5)CONSTRUCTOR,使用在构造器上面
public class Hello{
@Test
public Hello(){
}
}
(6)LOCAL_VARIABLE,使用在局部变量上面
public class Hello{
public void say(){
@Test
int num = -1;
}
}
(7)ANNOTATION_TYPE,使用在注解类型上面
@Test
public @interface Hello{
}
(8)PACKAGE,使用在包上面
@Test
package com.Test.test01;
包注解只能写在package-info.java文件中,package-info.java文件里面,只能包含package声明,并做出描述,以便将来生成doc文件,可以从API源码src.zip中,看到每个包下面都可以对应的package-info.java文件对该包做出描述
(9)TYPE_PARAMETER,使用在声明泛型参数前面(jdk1.8新增)
public class Hello{
//使用下面代码中定义的注解@Test T
public <@Test T> void sendMsg(T t){
}
}
//定义一个注解
interface Action<@Test t>{
}
(10)TYPE_USE,使用在代码的任何类型前面
public class Hello{
public void say(@Test String name){
List<@Test String> list = null;
Object obj = new @Test String("hello");
String str = (@Test String) obj;
}
}
关于注解的使用范围都定义在了一个枚举类中,这个类在java.lang.annotation包下
4、注解保持策略
类中使用的注解,根据配置,可以保持到三个不同的阶段:
SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃。
如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,使用SOURCE 注解。
CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃。
如果要在编译时进行一些预处理操作,比如生成一些辅助代码,就用 CLASS注解。
RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。
如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解,比如@Deprecated使用RUNTIME注解。
注解的三种保留策略,都定义在了一个枚举类中:
5、元注解
定义
元注解简单来说就是注解的注解。
常用到的元注解有
@Target,用于描述注解的使用范围,例如用在类上面还是方法上面。
@Retention,用于描述注解的保存策略,是保留到源代码中、Class文件中、还是加载到内存中。@Documented,用于描述该注解将会被javadoc生产到API文档中。
@Inherited,用于表示某个被标注的类型是被继承的,如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
例如:
(1)注解用于方法上,只保留在源文件中
@Target(ElementType.METHOD)
@Retenion(RetentionPolicy.SOURCE)
public @interfacee Override{
}
(2)注解会被javadoc生产到API文档中,保存到class文件中,jvm加载class文件之后,仍然存在,使用范围构造器,属性,局部变量,包,方法参数前
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Targer(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated{
}
6、自定义注解与使用
Annotation是专门用来写注解代码的
示例一:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
使用:
@Test
public class Service{
}
实例二:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
//角色名称
String name() default "";
//name属性的别名,使用value可以简化配置
String value() default "";
}
使用:
public class Service{
@Role(name = "admin")
public void delete(long id){
//...
}
@Role
public void find(long id){
//...
}
}
@Role(value=“admin”)代码,等价于@Role(“admin”),对应其他注解也同样适用