Java注解使用及原理解析

 更新时间:2020年06月09日 09:28:32   作者:护花使者  
这篇文章主要介绍了Java注解使用及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

基本特性

1、jdk 1.5之后才引入的。

2、用来说明程序的。(注释是给程序员看的,注解就是给电脑看的)

java注解的作用分类

1、编写文档:通过代码标识的注解生成文档。【生成doc文档】

2、代码分析:通过代码标识的注解对代码进行分析。【使用反射】

3、编译检查:通过代码标识的注解让编译器能够实现基本的编译检查。【override】

测试类:

/**
 * 我的javadoc测试
 */
public class TestCode {
  /**
   * 计算两个数的和
   * @param a 整数a
   * @param b 整数b
   * @return 返回两个数的和
   */
  public int add(int a, int b){
    return a+b;
  }
}

对于2、3两点我们应该是知道的。尽管可能不知道里面的原理。但是是平时都在用的。但是对于1点还可以生成doc文档?

测试操作如下:

D:\soft\jdk\bin\javadoc.exe .\TestCode.java -encoding utf-8 -docEncoding utf-8 -charset utf-8

生成了一大堆的东西:

打开TestCode.html可以发现,我们的java api手册就是这样生产的。

注解来源分类

1、jdk自带的注解,如常见的override(重写校验),deprecated(表示弃用)

2、自定义的注解

1)格式, 以override为例:

2)注解的本质

我们编写一个简单的注解

MyAnnotation.java

public @interface MyAnnotation {}

我们通过编译和反编译看下最终是什么样的结果:

D:\soft\jdk\bin\javac.exe MyAnnotation.java

D:\soft\jdk\bin\javap.exe MyAnnotation.class

结果如下:

public interface MyAnnotation extends java.lang.annotation.Annotation {

}

可以发现注解的本质就是接口,这个接口继承了jdk里面的Annotation接口。

3)注解的属性

由于注解本质为接口,那么里面可以定义未实现的方法。这些称为注解的“属性”。

属性的返回类型有(返回值不能为void):

  • 基本数据类型
  • String
  • 枚举
  • 注解
  • 以及以上四种类型的数组

例子:

public enum Person {
  PS;
}
public @interface Annotation2 {
}
public @interface MyAnnotation {
  String stringValue();
  int integerValue();
  Person personValue();
  Annotation2 myAnnotationValue();
  String[] stringArrayValue();
}

属性的使用,需要注意几点:

  • 定义了属性在使用的时候就要给属性赋值,除非设置default值。如:String stringValue() default "aaa";
  • 如果属性为value且属性只有这一个,那么value可以省略,直接填写属性值。
  • 如果是数组,需要用{}包含起来。
public @interface MyAnnotation {
  String stringValue() default "xxx";
  int integerValue();
  String[] stringArrayValue();
}

public @interface Annotation2 {
  String value();
}

@MyAnnotation(integerValue = 1, stringArrayValue = {"aaa", "bbb"})
@Annotation2("default")
public class TestCode {
  /**
   * 计算两个数的和
   * @param a 整数a
   * @param b 整数b
   * @return 返回两个数的和
   */
  public int add(int a, int b){
    return a+b;
  }

  @Override
  public String toString() {
    return super.toString();
  }
}

元注解

元注解是你在编写注解的时候,上面加的注解,就是注解的注解。主要有4个。

  • @target, 用于指定注解的使用位置。如@Target(ElementType.ANNOTATION_TYPE),@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})。
  • @Inherited,表示父类加了这个注解,子类也自动加上。
  • @Documented, 表示这个注解的信息在执行javadoc的时候是否抽取到api文档中。
  • @Retention,表示注解被保留的阶段,java类,class文件,以及被jvm读取。总共三种。RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME

元注解的内容,可以到jdk源码里面看一下,更有利于理解。

解析注解

这个是最关键了,以上加了这么多的属性,并且还为这些属性附了值,那么是希望程序读取这些值,进行使用的。那其实就是要看如何拿到这些注解配置的值。

测试:

MyAnnotition.java:

package annotation_;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
  String stringValue() default "xxx";
  int integerValue();
}

TestCode.java:

package annotation_;
@MyAnnotation(integerValue = 1)
public class TestCode {
  public static void main(String[] args) {
    Class<TestCode> testCodeClass = TestCode.class;
    MyAnnotation myAnnotation = testCodeClass.getAnnotation(MyAnnotation.class);
    int i = myAnnotation.integerValue();
    String s = myAnnotation.stringValue();
    System.out.printf("i = %d, s = %s\n", i, s);
  }
}

输出结果:

Connected to the target VM, address: '127.0.0.1:49586', transport: 'socket'
i = 1, s = xxx
Disconnected from the target VM, address: '127.0.0.1:49586', transport: 'socket'

Process finished with exit code 0

是不是感觉可以当配置文件使用。但是最主要的问题是myAnnotation.integerValue(),myAnnotation.stringValue()为什么可以拿到对应的值,这个也是最核心的问题。

那就是getAnnotation里面返回了一个实现了MyAnnotation注解(注解的本质是接口)的实例。这个类大概是长这样的。

package annotation_;

import java.lang.annotation.Annotation;

public class MyAnnotationImpl implements MyAnnotation{
  public String stringValue() {
    return "xxx";
  }
  public int integerValue() {
    return 0;
  }
  public Class<? extends Annotation> annotationType() {
    return null;
  }
}

所以就可以通过抽象方法获取到对应的值。(如何生成这样的一个类,只是学习注解,可以不关心。要不然,只能看里面的源码。因为如果自定义注解,你只会用到这一步,去获取值。)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 简单了解JAVA NIO

    简单了解JAVA NIO

    这篇文章主要介绍了JAVA NIO的的相关资料,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • java出现no XXX in java.library.path的解决及eclipse配置方式

    java出现no XXX in java.library.path的解决及eclipse配

    这篇文章主要介绍了java出现no XXX in java.library.path的解决及eclipse配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • JavaWeb实现邮件发送功能

    JavaWeb实现邮件发送功能

    这篇文章主要为大家详细介绍了JavaWeb实现邮件发送功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Spring Security OAuth 个性化token的使用

    Spring Security OAuth 个性化token的使用

    这篇文章主要介绍了Spring Security OAuth 个性化token的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • MAC下如何设置JDK环境变量

    MAC下如何设置JDK环境变量

    这篇文章主要介绍了MAC下如何设置JDK环境变量问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 不了解这12个语法糖,别说你会Java

    不了解这12个语法糖,别说你会Java

    这篇文章主要介绍了不了解这12个语法糖,别说你会Java,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • springboot打war包部署到外置tomcat容器的方法

    springboot打war包部署到外置tomcat容器的方法

    这篇文章主要介绍了springboot]打war包部署到外置tomcat容器,在这需要注意的是在boot-launch.war在tomcat webapps目录里面解压到boot-launch文件夹,感兴趣的朋友跟随小编一起看看吧
    2022-04-04
  • java实现快速打字游戏

    java实现快速打字游戏

    这篇文章主要为大家详细介绍了java实现快速打字游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • IDEA创建Servlet并配置web.xml的实现

    IDEA创建Servlet并配置web.xml的实现

    这篇文章主要介绍了IDEA创建Servlet并配置web.xml的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Java解析DICOM图之如何获得16进制数据详解

    Java解析DICOM图之如何获得16进制数据详解

    DICOM就是医学数字成像和通信,是医学图像和相关信息的国际标准(ISO 12052),下面这篇文章主要给大家介绍了关于Java解析DICOM图之如何获得16进制数据的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-10-10

最新评论