第二章注解深入浅出(一、注解 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();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值