Loading

Java 注解

注解简介

◆ Annotation是从JDK5.0开始引入的新技术.
◆ Annotation的作用:
  ➢不是程序本身,可以对程序作出解释.(这一点和注释(comment)没什么区别)
  ➢可以被其他程序(比如:编译器等)读取.
◆Annotation的格式:
  ➢注解是以"@注释名"在代码中存在的,还可以添加一些参数值,例如:
     @SuppressWarnings(value="unchecked").
◆Annotation在哪里使用?
  ➢可以附加在package , class , method , field等上面,相当于给他们添加了额外的辅助信息
     我们可以通过反射机制编程实现对这些元数据的访问。

JDK内置注解

@Overide :定义在java.lang.Override中,此注释只适用于修辞方法+表示一个方法声明打算
重写超类中的另一个方法声明
.
@Deprecated :定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示
鼓励程序员使用这样的元素
[ ,通常是因为它很危险或者存在更好的选择,)
@SuppressWarnings :定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,
我们选择性的使用就好了:

  • @SuppressWarnings("all")
  • @SuppressWarnings("unchecked")
  • @SuppressWarnings(value={"unchecked","deprecation"})

等等。

元注解

◆ 元注解的作用就是负责注解其他注解, Java定义了4个标准的meta-annotation类型,他们被用来
为其他annotation类型提供说明
◆ 这些类型和它们所支持的类在java.lang .annotation包中可以找到.( @Target , @Retention
@Documented , @Inherited )
@Target :(用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
@Retention :表示需要在什么级别保存该注释信息,用于描述注解的生命周期
➢ (SOURCE < CLASS < RUNTIME)
@Document:说明该注解将被包含在javadoc中
@Inherited: 说明子类可以继承父类中的该注解

1. @Target

如上所述,用于描述注解的使用范围,表明使用范围时需要在value参数中输入对应的枚举类型,即声明我们的注解可以放置在什么地方,如:

@Target(value = {ElementType.METHOD})
public @interface MyAnnotation {
}

此时表示注解可以用于修饰方法,例如:

public class Client {
    @MyAnnotation	<--
    public void test() {
    }
}

@Target注解源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

@Target所枚举的类型有:

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,
    /** Field declaration (includes enum constants) */
    FIELD,
    /** Method declaration */
    METHOD,
    /** Formal parameter declaration */
    PARAMETER,
    /** Constructor declaration */
    CONSTRUCTOR,
    /** Local variable declaration */
    LOCAL_VARIABLE,
    /** Annotation type declaration */
    ANNOTATION_TYPE,
    /** Package declaration */
    PACKAGE,
    // 1.8
    /**
     * Type parameter declaration
     */
    TYPE_PARAMETER,
    /**
     * Use of a type
     */
    TYPE_USE,
    // 1.9
    /**
     * Module declaration.
     */
    MODULE
}

2. @Retention

@Retention源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

该注解用于注明该注解可以在什么情况下有效,可填入的参数为RetentionPolicy的枚举类型,具体有:

public enum RetentionPolicy {
	// 源码时有效
    SOURCE,
    // 编译成class文件之后仍有效
    CLASS,
    // 运行时有效
    RUNTIME
}

遍写自定义注解时一般标RUNTIME,即运行时有效。

使用:

@Target(value = {ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)  <--
public @interface MyAnnotation {
}

有效范围:RUNTIME > CLASS > SOURCE

其余两个注解比较简单,再次不再赘述。

自定义注解

➢使用@interface自定义注解时,自动继承java.lang.annotation.Annotation接口

➢分析:

  • @ interface用来声明一个注解, 格式: public @interface 注解名{定义内容}
  • 其中的每一个方法实际上是声明了一个配置参数
  • 方法的名称就是参数的名称.
  • 方法前的类型就是参数的类型(只能是基本类型,Class , String , enum )
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值

编写一个自定义注解:

@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    // 注解的参数:参数类型 + 参数名()
    String name() default "";
    int age() default 18;
    int id() default -1;
    String[] schools() default {"北京大学","清华大学"};
}

tips: 如果参数没有默认值,则必须给注解对应参数赋值

如果注解的参数名为value,则可以在赋值时不需要写出参数名,即:

@MyAnnotation(value = "123")@MyAnnotation("123")

其实注解只是为程序提供一些修饰某部分的额外信息,并不能为程序提供直接的作用,即相当于在生产线上为产品标注上一些特定的信息,方便生产线后续的加工和生产。

因此要发挥注解的作用,我们一般需要在运行时使用反射来获取注解所标注的信息进行一些额外的处理等等。

posted @ 2021-08-03 22:41  CodeReaper  阅读(58)  评论(0编辑  收藏  举报