Java 注解

一、注解概述

官方:注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。

人话:注解类似于标签,相当于给一个东西贴上标签,让编译器能更好的认识它,从而进行处理。

  • 元数据

 元数据指的就是用来描述数据的数据,即注解是一种用来描述数据的数据。

二、元注解

元注解只是在使用的范围上有限制,它是用来给注解添加注解的。元注解一共就只有@Retention、@Documented、@Target、@Inherited、@Repeatable 这5种。

  • @Retention

 字面意思为保留。当它应用到一个注解上的时候,就可以解释说明当前注解作用的时间。这个保留策略(RetentionPolicy)它是一个枚举型,如果没有注解中没有声明元注解@Retention,则默认为RetentionPolicy.CLASS。

RetentionPolicy.CLASS:表明仅存在于源文件和经编译器编译后生成的字节码文件,在运行时VM不会保留注解。

RetentionPolicy.SOURCE仅存在于源文件,经编译器编译后便丢弃相应的注解。

RetentionPolicy.RUNTIME存在于源文件、编译后的字节码文件,还保留在运行时的VM中,可通过反射读取相应注解。

  • @Documented

 如果定义Annotation类时使用了@Documented修饰,则所有使用该Annotation修饰的程序元素的API文档中将会包含该Annotation说明。也就是说我们可以用它来编写文档。

  • @Target

 目标。即这个元注解限制了被修饰注解所能作用的范围。它也是一个枚举型,但是当注解中没有声明元注解@Target,则默认为能作用于所有地方。

ANNOTATION_TYPE:给一个注解进行注解。

CONSTRUCTOR:给构造方法进行注解。

FIELD:给属性进行注解。

LOCAL_VARIABLE:给局部变量进行注解。

METHOD:给方法进行注解。

PACKAGE:给一个包进行注解。

PARAMETER:给一个方法中的参数进行注解。

TYPE:可以给一个类型进行注解,比如类、接口、枚举

  • @Inherited

 遗传。类似于类的继承关系。举个例子,如果A这个类被xx注解,现在B这个类是A的子类,那么B就自动拥有这个注解。

  • @Repeatable

可重复。即注解的值可以同时取多个 ,就像一个人可以有多个身份,他可以是学生、程序员、DJ...

三、常见的内建注解

@Override:用于告诉编译器我们需要覆写超类的当前方法。

@Deprecated:告知编译器,某一属性、方法等过时了,我们常见一个方法被划了一根线就说明那个方法是被@Deprecated注解过的。

@SuppressWarnings:告知编译器忽略指定警告。在我们使用了这个后编译器将不会报出警告信息。

@SafeVarargs:参数安全类型注释,它会阻止编译器发出unchecked这样的警告,但是如果在实际应用中,开发者写了这个注解,但是参数实际是有错误的,这时它虽然不会在编译阶段发出警告,但是在运行时还是会抛出异常。

@FunctionalInterface:为响应函数式编程的号召,在java1.8中加入了这个注解。用户告知编译器,检查这个接口,保证该接口是函数式接口,即只能包含一个抽象方法,否则就会编译出错。

四、自定义注解

在自定义注解之前,我们还需要了解下注解的属性

  • 注解的属性

 注解的属性也叫成员变量,且注解只有成员变量,没有方法。但是注解的成员变量的声明同一般的成员变量声明有很大的区别。

注解的成员变量在注解的定义中以“无形参的方法”来声明。返回值即成员变量类型,方法名即变量名。并且我们可以通过default关键字为成员变量赋一个初始值。

import java.lang.annotation.*;

//元注解
@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
//通过@interface关键字来声明一个注解
public @interface TestAnnotation{
    //-> String name
    String name();
    //-> String website = "hello"
    String website()default "hello";
    //->int revision = 1
    int revision()default 1;
}

 通过上面代码,我们就简单的自定义了一个注解,可以看到这个注解仅包括元注解、属性,但它也算是一个完整的注解了。

五、注解的解析

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

这是我们之前了解过的反射机制,可以看到反射机制是作用于运行状态中的,所以这就限制了我们去动态解析注解的范围——必须要在运行状态还保留。这就涉及到@Retention这个元注解了,回顾一下,发现只有被声明为RUNTIME才能利用反射机制进行解析了。

@TestAnnotation(name="Mike")
public class Annotation {
    public static void main(String[] args) {
        System.out.println("I am main method");
        //Class类对象的isAnnotationPresent能够判断出是否应用了某个注解
        boolean hasAnnotation = Annotation.class.isAnnotationPresent(TestAnnotation.class);

        System.out.println(hasAnnotation);
        if (hasAnnotation){
            //获取类的注解
            TestAnnotation testAnnotation = Annotation.class.getAnnotation(TestAnnotation.class);
            //访问注解中的成员变量
            System.out.println("name: "+testAnnotation.name());
            System.out.println("website: "+testAnnotation.website());
            System.out.println("revision: "+testAnnotation.revision());
        }
    }
}

 上面我们只获取了类的注解,并对其所有成员变量进行了访问,但是我们还能获取方法中及成员变量的注解,大致写法都是类似的。

本文参考自一位大神的博客,加了些许自己的理解,供大家参考,如有不足请指出!谢谢!

https://blog.csdn.net/briblue/article/details/73824058

你可能感兴趣的:(Java 注解)