JAVA中注解 annotation的定义与使用

annotation定义

  • 注解,或者叫做注释类型,英文单词是:Annotation
  • 注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件。

annotation的语法格式

[修饰符列表] @interface 注解类型名{
 }

idea中创建注解类:
在这里插入图片描述

类的内容:

package com.hyg.annotation;

public @interface MyAnnotation {
}

annotation可以使用在的地方

注解可以使用在类上、属性上、方法上、变量上等,也可以使用在注解类型上。默认情况下注解可以出现在任何地方。

package com.hyg;

import com.hyg.annotation.MyAnnotation;
//使用在类上
@MyAnnotation
public class MyNanotationTest {
    //使用在属性上
    @MyAnnotation
    private int i;
    //使用在构造方法上
    @MyAnnotation
    public MyNanotationTest(){}
    //使用在静态方法上
    @MyAnnotation
    public static void test(){
        //使用在局部变量上
        @MyAnnotation
        int j=100;
    }
    //使用在成员方法上、形参上
    @MyAnnotation
    public void test1(@MyAnnotation int a){
    }

}
//使用在接口上
@MyAnnotation
interface MyInterface{

}
//使用在枚举上
@MyAnnotation
enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}
package com.hyg.annotation;
//使用在注解上
@MyAnnotation
public @interface OtherAnnotation {
}

JDK内置的注解和元注解

java.lang包下的注释类型:

  1. Deprecated 用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
    Deprecated 表示注解的方法已过时,可以使用在方法和类上,构造函数上
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
public class DeprecatedTest {
    @Deprecated
    public void test(){
        System.out.println("deprecated");
    }
}

在这里插入图片描述
在运行时编译器会有提示:

Warning:(6, 19) java: com.hyg.DeprecatedTest中的test()已过时

  1. Override 表示一个方法声明打算重写超类中的另一个方法声明。
    @Override
    public String toString(){
      return "test";  
    }

Override 可以看到这个注解里什么都没有,他就是用来给编译器检查使用的,和运行阶段没有关系,只能出现在方法上,用来检查是否是重写父类的方法,如果这个方法不是重写父类的方法,编译器就会报错。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
  1. SuppressWarnings 指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
元注解

一个注解用来修饰注解类型的一般称为元注解
常见的元注解:
Target:这个注解是用来标注被标识的注解可以出现在哪些位置上。

@Target(ElementType.METHOD) //表示被修饰的注解只能出现在方法上

ElementType是一个枚举类型,里面的属性都表示可以出现的位置

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
}

Retention:这个注解是来表示被标注的注解最终保存到哪里
RetentionPolicy枚举类

@Retention(RetentionPolicy.SOURCE)//表示该注解只被保留在java源文件中,在编译成class文件后就不会存在于class文件中
@Retention(RetentionPolicy.CLASS)//表示该注解被保留在class文件中
@Retention(RetentionPolicy.RUNTIME)//表示该注解被保留在class文件中,并且可以被放射读取

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

注解中的属性

我们通常在注解中自定义属性,下面的name就是MyAnotation的属性,看着像方法,实际上称之为属性name。

public @interface MyAnnotation {
    String name();
}

使用:
注意当我们的注解中有属性的时候,在使用它就必须为属性赋值,否则报错
赋值方式就是(属性名=属性值),至于属性值是什么类型取决于注解中属性的类型,有多个属性就得意义赋值

    @MyAnnotation(name = "myTest")
    public void doTest(){
        
    }

多个属性的使用:

public @interface MyAnnotation {
    String name();
    int age();
}
    @MyAnnotation(name = "myTest",age=18)
    public void doTest(){

    }

给属性指定默认值,当我们给属性指定默认值之后,在使用时可以不加上已经指定默认值的属性。

public @interface MyAnnotation {
    String name();
    int age() default 18;
}
    @MyAnnotation(name = "myTest")
    public void doTest(){

    }

关于value的使用:如果注解中的属性名字为value,并且只有一个属性的话,在使用的使用value属性名可以省略不写,只有属性名为value才可以省略,其他的属性名不可以

public @interface OtherAnnotation {
    String value();
}
    @OtherAnnotation(value = "hahaha")
    public void doOther(){

    }
    @OtherAnnotation("hahaha")
    public void doOther1(){

    }

再来看看,当一个注解中属性名有value并且也有多个属性的情况下value的属性名是否可以省略不写,从下面的截图中可以看到报错了,所以说明当注解中仅有一个属性并且属性名必须为value在使用的时候才可以省略属性名。

public @interface OtherAnnotation {
    String value();
    int age();
}

在这里插入图片描述

注解的属性类型

注解中的属性类型:
byte、short、int、long、float、double、boolean、char、String、Calss、枚举类型以及以上类型的数组形式。

public @interface MyAnnotation {
    int age() default 18;
    int[] value();
    String name();
    String[] value1();
    Season value2();
    Season[] value3();
    Class paramterType();
    Class[] paramterTypes();
}
public enum Season {
    SPRING,SUMMER,AUTUMN,WINTER
}

属性是数组的使用:

public @interface OtherAnnotation {
    String[] value();
    int age();
}

当数组中只有一个值时,大括号可以省略

    @OtherAnnotation(value = {"hahaha","hehehehe"},age=18)
    public void doOther(){

    }
    @OtherAnnotation(value = "hahaha",age=18)
    public void doOther1(){

    }

属性是枚举类型

public @interface OtherAnnotation {
    String[] value();
    int age();
    Season[] season();
}
    @OtherAnnotation(value = {"hahaha","hehehehe"},age=18,season = Season.AUTUMN)
    public void doOther(){

    }
    @OtherAnnotation(value = "hahaha",age=18,season = {Season.AUTUMN,Season.SPRING,Season.SUMMER})
    public void doOther1(){

    }
        @OtherAnnotation(value = "hahaha",age=18,season = {AUTUMN,SPRING,SUMMER})
    public void doOther2(){

    }

annotation的使用

经过上面的讲解,我们应该会怎么去定义和在使用注解了,现在就往下看看注解在项目中的真正的用法。

  • 反射判断类上是否存在注解
    首先在注解上声明该类可以使用的地方和保存的方式,注意只有注解上@Retention(RetentionPolicy.RUNTIME) 才可以被放射获取到
@Target(value = {TYPE,FIELD,METHOD,})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int age() default 18;
    String name();
}
@MyAnnotation(name = "test")
public class MyTest {
    @MyAnnotation(name = "myTest")
    public void doTest(){

    }

    @OtherAnnotation(value = {"hahaha","hehehehe"},age=18,season = AUTUMN)
    public void doOther(){

    }
    @OtherAnnotation(value = "hahaha",age=18,season = {AUTUMN,SPRING,SUMMER})
    public void doOther1(){
    }
}

测试反射获取判断注解是否存在

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //先获取class对象
        Class c=Class.forName("com.hyg.MyTest");
        //判断该类上是否有@MyAnnotation注解
        if(c.isAnnotationPresent(MyAnnotation.class)){
            //做相关的逻辑处理
            System.out.println("做相关的逻辑处理");
        }
        else {
            System.out.println("该类上没有@MyAnnotation注解");
        }
    }
}

结果
在这里插入图片描述
获取类上的注解对象和注解的属性:

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //先获取class对象
        Class c=Class.forName("com.hyg.MyTest");
        //判断该类上是否有@MyAnnotation注解
        if(c.isAnnotationPresent(MyAnnotation.class)){
            //获取类上的注解,可以获取多个  Annotation[] annotations = c.getAnnotations();
            MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
            System.out.println("类上的注解对象"+annotation);
            //获取注解的属性,跟调用接口一样
            String name = annotation.name();
            int age = annotation.age();
            System.out.println(name+age);

            //做相关的逻辑处理
            System.out.println("做相关的逻辑处理");
        }
        else {
            System.out.println("该类上没有@MyAnnotation注解");
        }
    }
}

获取方法上注解的相关信息:

public class ReflectMethod {
    public static void main(String[] args) throws Exception {
        //先获取类
        Class c=Class.forName("com.hyg.MyTest");
        //在获取方法
        Method doTest = c.getDeclaredMethod("doTest");
        //判断方法上是否有@MyAnnotation注解
        if (doTest.isAnnotationPresent(MyAnnotation.class)){
            //获取方法上的注解
            MyAnnotation annotation = (MyAnnotation) doTest.getAnnotation(MyAnnotation.class);
            System.out.println("方法上的注解对象"+annotation);
            //获取注解的属性
            String name = annotation.name();
            int age = annotation.age();
            System.out.println(name+age);
            //做相关的逻辑处理
            System.out.println("做相关的逻辑处理");
        }
        else {
            System.out.println("该类上没有@MyAnnotation注解");
        }

    }
}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值