1. 优享JAVA首页
  2. Java
  3. 注解

Java注解的基本介绍

Java注解(annotation),它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。

概念

Java注解是在JDK1.5时引入的新特性,由于很多流行框架中都使用过注解,因此掌握Java注解是对于Java工程师来说的一项必备技能。

本篇文章作为《Redis注解实现》专题的开篇,会介绍一些常见的注解,以及注解的使用语法等。

理解Java注解

public class Student {
    //可以在一个方法上使用多个注解
    @Deprecated  //Java内置注解,用于标识方法过期不建议使用
    @SuppressWarnings("uncheck") //忽略警告标识
    public static void read() { }
    
    @Test // 使用@Test注解修饰的方法
    public void write(){ read(); }
}

@Test是测试框架中的一个注解,在方法上使用@Test注解,测试框架会自动识别该注解标识的方法,@Deprecated和@SuppressWarnings(“uncheck”) 是Java中内置的注解,并且也是我们经常用到的。

元注解与语法

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
} 

上面我们用到的@Target、@Retention称为元注解,元注解也就是注解的注解

@Target 元注解, 用于指定标记类型,ElementType.METHOD表示这个注解是被用于到方法上的。

@Retention() 元注解,用于指定注解的保留期是什么,保留期是什么意思呢?实际上上面代码中给定的参数RetentionPolicy.RUNTIME表示该注解用于运行时环境,也就是说这个注解只会在运行时环境中生效。

@interface这个关键字用于标识该类是一个注解类

@Target所有可用参数定义在枚举类ElementType中,具体如下:

public enum ElementType {
    /** 类、接口(包括注释类型)或枚举声明 */
    TYPE,
    /** 字段声明(包括枚举常量) */
    FIELD,
    /** 方法声明 */
    METHOD,
    /** 参数声明 */
    PARAMETER,
    /** 构造函数声明 */
    CONSTRUCTOR,
    /** 局部变量声明 */
    LOCAL_VARIABLE,
    /** 注释类型声明 */
    ANNOTATION_TYPE,
    /** 包声明 */
    PACKAGE,
    /** 类型参数声明,1.8版本新加入 */
    TYPE_PARAMETER,
    /** 类型的使用声明,1.8版本新加入 */
    TYPE_USE
}

当@Target不指定任何属性时,表示适用于上面所有范围。@Target可以指定多个值,具体格式如下:

@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})

@Retention 元注解有三个值,分别是 ( source )源码级别、(class)类级别、(runtime)运行时,含义如下:

  • SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
  • CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
  • RUNTIME:注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等。

通过上面的@Test注解,我们简单了解了注解的的定义过程,不过@Test注解和自定义注解还是有一些区别的,由于@Test注解内部没有定义任何元素,一般称这样的注解为标记注解,下面我们看看自定义注解定义:

@Target(ElementType.TYPE)//只能应用于类上
@Retention(RetentionPolicy.RUNTIME)//保存到运行时
public @interface DBTable {
    String name() default "";
}

我们定义了一个名为DBTable的注解,用于数据库表和Bean类的映射关系,与前面的@Test注解不同,@DBTable注解中我们声明了一个String类型的元素,给定默认值为空。

除了String类型的元素外,注解的声明中还支持下面几种类型:

  • 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  • String
  • enum
  • 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)
@interface Reference {
    boolean next() default false;
}

@Target(ElementType.TYPE)//只能应用于类上
@Retention(RetentionPolicy.RUNTIME)//保存到运行时
public @interface DBTable {
    //枚举类型
    enum Status { FIXED, NORMAL }
    //声明枚举
    Status status() default Status.FIXED;
    //布尔类型
    boolean showSupport() default false;
    //String类型
    String name() default "";
    //class类型
    Class<?> testCase() default Void.class;
    //注解嵌套
    Reference reference() default @Reference(next = true);
    //数组类型
    long[] value();
}

另外注解是不支持继承的,因此不能使用关键字extends来继承某个@interface,注解类编译之后,默认会自动继承Annotation接口。

注解中定义了名称为value的元素,如果该元素是唯一需要赋值的元素,可以直接在括号内给出元素的值,条件是元素名称必须是value

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBColumn {
    String value() default "";
    int size() default 3;
}

//使用注解
public class Test {
    //当只想给value赋值时,可以使用以下方式
    @DBColumn("age")
    public int age;

    //当size也需要赋值时必须采用key=value的方式赋值
    @DBColumn(value = "MONEY",size = 2)
    public int money;
}

原创文章,作者:Craig,如若转载,请注明出处:https://www.goodlymoon.com/archives/1491.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

QR code