46_注解

59 篇文章 2 订阅
22 篇文章 1 订阅

注解

注解的基本概念

  • 注解(Annotation)又叫标注,是从java5开始增加的一种引用数据类型。跟枚举一样是从Java5开始增加的,枚举我们就看做是一种特殊类,注解就看做是一种特殊的接口即可。
  • 注解本质上就是代码中的特殊标记,通过这些标记可以在编译、类加载、以及运行时执行指定的处理。就像超市的货架上的标签一样。就是对代码做一些特殊声明,以及代码补充之类的。

注解的语法格式

  • 访问修饰符  @interface 注解名称 {	@interface 就是在告诉我们注解是一种特殊的接口
    	注解成员;
    }
    
  • 自定义注解自动继承java.lang.annotatiob.Annotation接口。

  • 通过@注解名称 的方式可以修饰包、类、成员方法、成员变量、构造方法、参数、局部变量的声明等

注解的使用方式

  • 注解体中只有成员变量没有成员方法,而注解的成员变量以"无形参的方法(无形参的抽象方法)"形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
  • 如果注解中只有一个参数成员,建议使用参数名为value,而类型只能是八种基本数据类型、String类型、Class类型、enum类型及Annotation类型

元注解

  • 元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面。元注解不能应用在类上。
  • 元注解主要有:@Retention、@Documented、@Target、@Inherited、@Repeatable。
  • @Retention:保持的意思,主要描述的是注解的有效范围(生命周期)
  • @Documented:主要描述的是这个注解是否在文档注释中体现
  • @Target:目标的意思,表示这个注解到底可以修饰哪些内容
  • @Inherited:是继承的意思,表示注解是否可以被继承到我所标记的类的子类中
  • @Repeatable:是否可以重复

元注解@Retention

  • @Retention 应用到一个注解上用于说明该注解的生命周期,取值 如下:
  • RetentionPolicy.SOURCE 注解只在源码阶段(.java)保留,在编译器进行编译时它将被丢弃忽视
  • RetentionPolicy.CLASS 注解只被保留到编译进行的时候(.class),它并不会被加载到 JVM 中(运行阶段就丢弃了),默认方式
  • RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载到 JVM 中,所以程序运行时可以获取到它们

元注解@Documented

  • 使用javadoc工具可以从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档,而该工具抽取时默认不包括注解内容。Idea是集成开发环境,已经不再需要使用控制台了,直接用导航栏的Tools–>Generate JavaDoc–>选择要生成文档的目标–>指定输出目录Output directory–> Other command line arguments: -encoding utf-8 指定其它命令行参数:编码格式为utf-8(防止中文乱码)–> Open generated documentation in browser(生成之后可以用浏览器打开) 注:输出目录最好不要有中文,代码存放路径绝对不能有中文。
  • @Documented用于指定该注解将被javadoc工具成文档
  • 定义为@Documented的注解必须设置Retention值为RUNTIME。
  • 此处我们提取注释和注解到D:\LGStudy\javadoc中了

元注解@Target

  • @Target 用于指定被修饰的注解能用于哪些元素的修饰,取值如下:
  • 在这里插入图片描述

元注解@Inherited

  • @Inherited 并不是说注解本身可以继承,而是说如果一个超类被该注解标记过的注解进行注解时,如果子类没有被任何注解应用时,则子类就继承超类的注解。
package com.lagou.module02.task05;

import java.lang.annotation.*; // *表示导入所有

/**
 * @author hhc19
 * @date 2022/1/2 11:03
 * @description
 */
// @Retention(RetentionPolicy.SOURCE)   // 表示下面注解在源代码中有效,一旦编译就没了
// @Retention(RetentionPolicy.CLASS)    // 表示下面注解在字节码文件中有效,到运行阶段就没了,默认方式
@Retention(RetentionPolicy.RUNTIME)     // 表示下面注解在运行时有效,在运行阶段依旧是有效、健在的
@Documented                             // 表示下面的注解信息可以被javadoc 工具提取到API文档中
// 表示下面的注解可以用于类型(类、接口、枚举)、构造方法、成员变量、成员方法、参数的修饰,不加该注解默认都有
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Inherited                              // 表示下面的注解所修饰的类中的注解可以被子类继承
// 若一个注解中没有任何的成员,则这样的注解叫做标记注解/标识注解
// 这个注解仅仅是打了一个标记/做了一个标识而已
public @interface MyAnnotation {
    // ctr + shift + 回车 直接到下一行
    public String value() default "默认值"; // 声明一个String类型的成员变量,名字为value, 这个在之前的学习中是定义了一个名为value的抽象方法

    // public Direction ss();Error: Invalid type 'Direction' for annotation member 无效的类型,类型有要求
    public String value2();
}




package com.lagou.module02.task05;

/**
 * @author hhc19
 * @date 2022/1/2 11:03
 * @description
 */
// 表示将标签MyAnnotation贴在Person类的代码中,使用注解时采用 (成员参数名 = 成员参数值, ...) 的方式对注解中的成员进行初始化

/** 注解中不想给值的两种情况:
 *      1、注解中没有任何的成员时(标记接口,标记注解);
 *      2、如果有两个成员的时候还是不想给值:使用default关键字给成员变量给一个默认值,在使用注解的时候就可以不给值;
 *          有默认值的时候也可以传值。
 */
// @MyAnnotation(value = "hello", value2 = "world")
@MyAnnotation(value2 = "world") // MyAnnotation not application to type MyAnnotation不能应用在类型上
// @Retention(RetentionPolicy.RUNTIME)  元注解只能标注在注解上。
public class Person {

    /**
     * name是用于描述姓名的成员变量
     */
    @MyAnnotation(value2 = "1")
    private String name;
    /**
     * age是用于描述年龄的成员变量
     */
    private int age;

    /**
     * 编程实现无参构造方法
     */
    @MyAnnotation(value2 = "2")
    public Person() {
    }

    /**
     * 编程实现有参构造方法
     * @param name
     * @param age
     */
    public Person(@MyAnnotation(value2 = "4") String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 自定义成员方法实现特征的获取和修改
     * @return 代表返回值的注解
     */
    @MyAnnotation(value2 = "3")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}



package com.lagou.module02.task05;

/**
 * @author hhc19
 * @date 2022/1/2 14:15
 * @description
 */
// 也就是可以继承Person类的注解,前提是Person类上标注的注解上标注了 @Inherited
public class Student extends Person {
}

元注解@Repeatable

  • @Repeatable表示自然可重复的含义(这个注解可以被多次使用),从Java8开始增加的新特性。在一个类上多次重复使用。

  • 从Java8开始对元注解@Target的参数类型ElementType枚举值增加了两个:

  • 其中ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中,如泛型。

  • 其中ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中

    package com.lagou.module02.task05;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Repeatable;
    import java.lang.annotation.Target;
    
    /**
     * @author hhc19
     * @date 2022/1/2 14:20
     * @description 自定义注解用于描述人物的角色
     */
    // 下面的注解本来是不能实现多次使用的,要想多次使用实际上还是得依赖于ManTypes那种数组的形式,所以我们就把那个放数组的那个注解拿过来放这
    // 但是此处需要一个Class对象,所以就.class,从此以后MainType注解就可以重复使用
    // ManType制定了Target之后,在ManTypes中也要指定
    @Repeatable(value = ManTypes.class) // Target of container annotation 'com.lagou.module02.task05.ManTypes' is not a subset of target of this annotation
    @Target(ElementType.TYPE_USE)
    public @interface ManType {
        String value() default "";
    }
    
    
    
    package com.lagou.module02.task05;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    /**
     * @author hhc19
     * @date 2022/1/2 14:24
     * @description 自定义注解里面可以描述多种角色
     */
    @Target(ElementType.TYPE_USE)
    public @interface ManTypes {
        ManType[] value();
    }
    
    
    
    package com.lagou.module02.task05;
    
    /**
     * @author hhc19
     * @date 2022/1/2 14:22
     * @description
     */
    
    // @ManTypes({@ManType("职工"), @ManType("超人")}) // 在Java8处理多个注解的方式,此时既满足了我们只用一次注解的方式,又可以使用两种值的形式
    // Duplicate annotation. The declaration of 'com.lagou.module02.task05.ManType' does not have a valid java.lang.annotation.Repeatable annotation
    // MainType并不是一个可重复的注解,本质上它还是依赖于ManTypes中的数组去处理
    @ManType("职工")
    @ManType("超人")
    public class Man {
    
        public static void main(String[] args) {
            int ia = 97;
            // char c1 = (@ManType  char) ia; '@ManType\' not applicable to type use'
            char c1 = (@ManType  char) ia;
        }
    }
    
    
    
    package com.lagou.module02.task05;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    /**
     * @author hhc19
     * @date 2022/1/2 15:05
     * @description
     */
    @Target(ElementType.TYPE_PARAMETER)
    public @interface Test {
    }
    
    
    
    public static <@Test T> void print(T[] inputArray) {}
    

常见的预制注解

  • 预制(预先制定)注解就是Java语言自身提供的注解,具体如下:在这里插入图片描述

  • 常用的预制注解如下:

    @Override 限定重写父类的方法,该注解只能用于方法
        
    @Deprecated 用于表示所修饰的元素(类、方法等)已过时
        
    @SuppressWarnings 抑制编译器警告,一般用在eclipse中,idea用得很少。
        
    @Deprecated // 表示该方法已经过时,不建议再使用了
    public void show() {
        System.out.println("这个方法马上过时了...");
    }
    
    public class ManTest {
    
        public static void main(String[] args) {
    
            Man man = new Man();
            man.show(); // 'show()' is deprecated show方法已经过时了,不建议使用了
        }
    }
    

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值