Hefery 的个人网站

Hefery's Personal Website

Contact:hefery@126.com
  menu
73 文章
0 浏览
6 当前访客
ღゝ◡╹)ノ❤️

Java基础—注解

注解简介

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

作用:

  • 编写文档:通过代码里标识的注解生成文档(生成文档doc文档)
    /**
     * @Author:Hefery
     * @Version:1.0.0
     * @Date:2022/3/15 12:03
     * @Description:
     */
    public class AnnotationDemo {
    
        /**
         * 两数相加
         * @param a 加数
         * @param b 加数
         * @return 和
         */
        public int add(int a, int b) {
            return a + b; 
        }
    
    }
    
  • 代码分析:通过代码里标识的注解对代码进行分析(使用反射)
  • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查(如@Override)

JDK预定义注解

作用在代码层面的注解

  • @Override:检查该方法是否是重写方法。果发现其父类,或是引用的接口中并没有该方法,报编译错误

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }
    
  • @Deprecated:标记过时方法。如果使用该方法,会报编译警告

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    
  • @SuppressWarnings:指示编译器去忽略注解中声明的警告

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }
    
// @SuppressWarnings:指示编译器去忽略注解中声明的警告
@SuppressWarnings("all")  // 会警告类中有未使用的方法,类上标注 @SuppressWarnings 就是要压住警告
public class AnnotationDemo {

    // @Override:检查该方法是否是重写方法。果发现其父类,或是引用的接口中并没有该方法,报编译错误
    @Override
    public String toString() {
        return super.toString();
    }

    // @Deprecated:标记过时方法。如果使用该方法,会报编译警告
    @Deprecated
    public void show1() {
        // 有缺陷,建议使用 show2() 方法
        // 不能删,要兼容使用到 show1() 方法
    }

    public void show2() {
        // 替代 show1() 方法
    }

    public void showDemo() {
        show1();  // 删除线提示该方法已过时或已弃用
        show2();
    }

}

作用在其他注解的注解—元注解

  • @Retention:标识这个注解怎么保存。描述注解被保留的阶段,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
        RetentionPolicy value();
    }
    
    public enum RetentionPolicy {
        /**
         * 源代码Source阶段
         */
        SOURCE,
    
        /**
         * 类对象 Class 阶段
         */
        CLASS,
    
        /**
         * 运行时Runtime阶段,自定义注解一般使用
         */
        RUNTIME
    }
    
  • @Documented:标记这些注解是否包含在用户 API 文档中
  • @Target:标记这个注解应该是哪种 Java 成员,能够作用的位置
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
        ElementType[] value();
    }
    
  • @Inherited:标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
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,

    /**
     * Type parameter declaration
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     * @since 1.8
     */
    TYPE_USE
}

从Java 7开始,新增的注解

  • @SafeVarargs:Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
  • @FunctionalInterface:Java 8 开始支持,标识一个匿名函数或函数式接口
  • @Repeatable:Java 8 开始支持,标识某注解可以在同一个声明上使用多次

自定义注解

了解注解本质

注解本质:默认继承 Annotation 类的接口

在 IDEA 编辑 HeferyAnnotation 注解:public @interface HeferyAnnotation {}

编译:javac HeferyAnnotation.java,生成 .class 文件

反编译:javap HeferyAnnotation.class,控制台输出public interface HeferyAnnotation extends java.lang.annotation.Annotation { }

注解属性定义

注解格式:

@元注解
public @interface 注解名称 {
	// 属性列表
}

注解属性:接口中的抽象方法

注解属性要求:

  • 返回值:基本数据类型、String、枚举、注解、以上类型的数组
  • 使用:使用注解属性要给属性赋值
    如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值
    数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}省略

自定义注解:

@Documented  // 标记这些注解是否包含在用户 API 文档中
@Target(value = {ElementType.TYPE, ElementType.METHOD}) //当前被描述注解作用于类、接口、注解、枚举+方法
@Retention(RetentionPolicy.RUNTIME)  // 当前被描述的注解会保留到class字节码文件中,并被JVM读取到
public @interface HeferyAnnotation {
}


@HeferyAnnotation  // @Target(value = {ElementType.TYPE, ElementType.METHOD})
public class Worker {

    //@HeferyAnnotation  // 报错:'@HeferyAnnotation' not applicable to field
    public String workName;

    @HeferyAnnotation
    public void work() {
        System.out.println("工人最有力量");
    }

}

程序中使用注解

模拟注解想要调用 Demo 类的 show() 方法

public class Demo {

    public void show() {
        System.out.println("show Demo01 ...");
    }

}

自定义注解

/**
 * @Author:Hefery
 * @Version:1.0.0
 * @Date:2022/3/15 13:18
 * @Description:描述需要执行的类名,和方法名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PropertiesAnnotation {
    String className();
    String methodName();
}

使用注解实现调用 Demo 类的 show() 方法

@PropertiesAnnotation(className = "com.hefery.kafkademo.annotation.Demo", methodName = "show")
public class ReflectTest {

    public static void main(String[] args) {
        /**
         * 不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
         * 1. 反射:定义 .properties 文件去读取里面的内容,并封装到 Properties,通过反射将类加载至内存并 newInstance 创建对象,从而调用其方法
         * 2. 注解:
         */

        // 1. 解析注解:获取该类的字节码文件对象
        Class<ReflectTest> reflectTestClass = ReflectTest.class;
        // 2 获取注解对象:在内存中生成了一个该注解接口的子类实现对象
        PropertiesAnnotation reflectTestClassAnnotation = reflectTestClass.getAnnotation(PropertiesAnnotation.class);
        // 3 调用注解对象中定义的抽象方法(属性)
        String className = reflectTestClassAnnotation.className();
        String methodName = reflectTestClassAnnotation.methodName();

        System.out.println(className);   // com.hefery.kafkademo.annotation.Demo01
        System.out.println(methodName);  // show
    }

}

标题:Java基础—注解
作者:Hefery
地址:http://hefery.icu/articles/2022/03/15/1647331307027.html