重温java中注解

115 阅读3分钟

注解

1、什么是注解

注解:可以理解就是一个类,可以通过属性设置参数

2、注解有什么用

注解可以使用在包、类、字段、方法、局部变量、方法参数等,用来对这些元素进行说明。在开发过程中,使用xml配置文件内容过多,导致程序难以维护,将使用注解取代xml配置文件。

3、怎么使用注解

接下来我们要学习怎么去定义注解,使用注解,然后再去解析注解。

在这之前我们先来看看jdk5提供的常用注解有哪些。

@Override jdk1.5表示子类复写父类的方法;jdk1.6中表示实现接口方法以及复写父类的方法
@Deprecated  过时了,建议不再使用,但还可以使用。
@SuppressWarnings() 抑制警告,通知编译器不进行错误报警
    "deprecation",  过时
    "rawtypes",  没有泛型
    "unused", 没有使用
    "null" , 空指针
    "serial" 序列号
    "all" 所有

3.1 定义注解

  • 定义语法:使用关键字@interface 来定义名叫Anno的注解
public @interface Anno {
}
  • 属性格式:
    [public abstract] 返回值类型 属性名() [default 默认值];

    返回值类型:基本类型(包装类型)、String、Class、注解、枚举enum 以及以上类型的一维数组

    属性名:自定义

public @interface Anno {
    public abstract String username() default "";
    public abstract long birthday();
    int age();
    Class clazz();
    Color color() default Color.red;
    Anno1 anno();
}

public @interface Anno1 {
    String value();
}

public @interface Annos {
    String[] value();
}

enum Color{
    red(),
    black()
}

3.2 使用注解

  • 在指定的位置(类、方法、字段、构造等) 使用格式: @注解名称(属性名称=值, 名称2=值2)
    • 属性名称:如果属性名称为value(eg:Anno1),使用时只有一对属性,此时value可以省略。
    //@Anno1(value = "")
    @Anno1("")
    public void demo(){
    }
    
    • 属性值:如果类型为数组(eg:Annos),需要使用{}进行扩展,多个值之间使用,进行分割;如果只有一个值,{}是可以省略的。
    //@Annos(value={"1", "2", "3"})
    //@Annos(value={"1"})
    @Annos(value="1")
    public void demo1(){
    }
    
    • 综合使用: 这里是使用在类上的注解,需要了解后面元注解的概念。
    @Anno(
        username = "sxd",
        age = 18,
        birthday = 12345678,
        clazz = Date.class,
        anno = {
                @Anno1("666"),
                @Anno1(value = "888")
        }
    )
    public class TestAnno {
    }
    

3.3 解析注解

我们将使用AnnotatedElement类下面的函数来解析注解

  • getAnnotation(Class annotationClass) 通过指定的注解的字节码获得注解实例
  • isAnnotationPresent(Class<? extends Annotation> annotationClass)  判断当前对象上是否包含指定的注解
  • getAnnotations() 获得所有的public的注解
  • getDeclaredAnnotations()  获得所有的注解(包括private)
@Anno1
@Anno2
@Anno3(username="java",password="test")
public class TestAnno {

	public static void main(String[] args) {
		//解析
		boolean a1 = TestAnno4.class.isAnnotationPresent(Anno1.class);
		boolean a2 = TestAnno4.class.isAnnotationPresent(Anno2.class);
		boolean a3 = TestAnno4.class.isAnnotationPresent(Anno3.class);
		System.out.println(a1);
		System.out.println(a2);
		System.out.println(a3);
		//获得数据
		if(a3){
			Anno4_3 anno = TestAnno4.class.getAnnotation(Anno4_3.class);
			System.out.println(anno.username());
			System.out.println(anno.password());
		}
	}
}

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@interface Anno1{
}

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
@interface Anno2{	
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
//@Inherited //子类都继承
@interface Anno3{
    String username();
    String password();
}

4、元注解

  • 元注解:用于修饰注解(自定义注解)的注解(JDK已经提供好的注解)。
    • @Retention 被修饰自定义注解的生命周期

      • @Retention(RetentionPolicy.SOURCE) , 被修饰的自定义注解,只能在源码中存在。提供编译器使用
      • @Retention(RetentionPolicy.CLASS), 被修饰的自定义注解,只能在源码和字节码中存在。提供JVM使用
      • @Retention(RetentionPolicy.RUNTIME), 被修饰的自定义注解,只能在源码、字节码和运行时中存在。提供程序获得数据
    • @Target 被修饰自定义注解,使用的位置;下面几个是经常使用的

      • @Target(ElementType.TYPE) 被修饰的自定义注解,只能在类或接口上使用
      • @Target(ElementType.CONSTRUCTOR) 被修饰的自定义注解,只能在构造方法上使用
      • @Target(ElementType.FIELD) 被修饰的自定义注解,只能在字段上使用
      • @Target(ElementType.METHOD) 被修饰的自定义注解,只能在普通方法上使用
      • @Documented  被修饰自定义注解,可以在javadoc生成的文档存在。
      • @Inherited 被修饰的自定义注解,所有子类都将继承该注解