注解深入浅出(一注解 Annotations)

Posted 持续学习刻意练习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了注解深入浅出(一注解 Annotations)相关的知识,希望对你有一定的参考价值。

第二章注解深入浅出

一、注解 Annotations

1.1 注解

注解是一种将元数据附加到代码中的方法。

注解(Annotation),也叫做元数据,一种代码级别的说明。 它是 JDK 1.5 及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注解。

Java 注解:声明注解需要在类前面使用 @interface 关键字:

public @interface MyAnnotation 

Kotlin 注解:声明注解需要在类前面使用 annotation 关键字:

annotation class MyAnnotation

android 注解的好处:

  • 简化代码,提高开发效率(不一定提高运行效率)
  • 更早的发现程序的问题或者错误
  • 更好的增加代码的描述能力
  • 更加利于我们的一些规范约束
  • 提供解决问题的更优解

1.2 元注解

元注解是用来定义其他注解的注解,简单来说,就是注解上的注解。

元注解共有四种:@Rentention、@Target、@Inherited、@Documented。

@Retention:注解保留的声明周期,默认值为 CLASS。对应 RetentionPolicy 的枚举,表示注解在何时生效,可选值有三种

  • SOURCE:只在源码中可用(当 Java 文件编译成 Class 文件的时候,注解被遗弃)
  • CLASS:在源码和字节码中可用(Jvm 加载 Class 文件的时候被遗弃,这是默认的声明周期)
  • RUNTIME:在源码、字节码和运行时均可用(Jvm 加载到 Class 文件之后,仍然存在)
    SOURCE < CLASS < RUNTIME,前者能作用的地方后者一定也能作用。

@Target:注解对象的作用范围,对应 ElementType 枚举,明确了注解的有效范围。ElementType 枚举中包括:

  • TYPE:类、接口、枚举、注解类型
  • FIELD:类成员(构造方法、方法、成员变量)
  • METHOD:方法
  • PARAMETER:方法参数
  • CONSTRUCTOR:构造函数
  • LOCAL_VARIABLE:局部变量
  • ANNOTATION_TYPE:注解
  • PACKAGE:包
  • TYPE_PARAMETER:类型参数
  • TYPE_USE:类型使用声明

@Inherited:注解是否可以被继承,默认为 false。用 @Inherited 声明出来的注解只对类有效,对方法/属性无效。

@Document:是否会保存到 Javadoc 文档中。

现在来看下 @Override 注解的源码:

package java.lang;

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

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Override 

分析一下,
@Retention(RetentionPolicy.SOURCE):表示 @Override 注解只在源码中使用,
@Target(ElementType.METHOD):表示 @Override 注解作用的范围在方法中,也就是用来修饰方法的。

1.3 自定义注解

自定义注解的时候,需要使用到元注解来定义我们自定义的注解。

举个例子讲解。

package com.example.demo;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target(FIELD)
public @interface TestAnnotation 

    String value();

    String[] value2() default "value2";


注解值的写法:类型 参数名() default 默认值;
其中默认值是可选的,可以定义,也可以不定义。

处理运行时注解

Rentention 的值为 RUNTIME 时,注解会保留到运行时,因此使用反射来解析注解。

还是用上一步的注解 @TestAnnotation,解析示例如下:

package com.example.demo;

import java.lang.reflect.Field;

public class Demo 

    @TestAnnotation("Hello Annotation")
    private String testAnnotation;

    public static void main(String[] args) 
        try 
            // 获取要解析的类
            Class clazz = Class.forName("myAnnotaiton.Demo");
            // 拿到所有 Filed
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) 
                // 获取 Field 上的注解
                TestAnnotation testAnnotation = field.getAnnotation(TestAnnotation.class);
                if (null != testAnnotation) 
                    // 获取注解值
                    String value = testAnnotation.value();
                    System.out.println("value = " + value);
                
            
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        
    

以上是关于注解深入浅出(一注解 Annotations)的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 注解 (Annotations 三)多对一双向注解

P4 开发实践 — 编程基础 — Annotations 注解

P4 开发实践 — 编程基础 — Annotations 注解

P4 开发实践 — 编程基础 — Annotations 注解

android Support Annotations(注解支持)

Support Annotations注解介绍以及自定义注解代替枚举