Java注解(Annotion)

Java注解(Annotion)

定义一个注解
package org.zj;

public @interface TestAnnotation {
}

你会发现,这个注解怎么和接口一样,实际上,注解就是一个继承Annotation的接口,我们可以反编译上边的代码看一下注解的本质

public interface org.zj.TestAnnotation extends java.lang.annotation.Annotation {
}
如何使用注解
package  org.zj;
@TestAnnotation
public class Student {
    @TestAnnotation
    private String name;
    
    @TestAnnotation
    public static void out(){
        System.out.println("我是一个学生");
    }
}

注解可以用在很多地方,具体的使用范围我们可以在后面的元注解中看到。

元注解

什么是元注解呢?作用于注解上的注解,就是可以用来修饰普通的注解。

@Retention

@Rentention修饰注解的时候,它可以决定注解的存活时间,它的取值为以下三种

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
}
  • RetentionPolicy.SOURCE,注解只在源码阶段保留,编译后注解将会被丢弃
  • RetentionPolicy.CLASS,注解会在源码阶段和字节码阶段(CLASS文件)被保留,但不会加载到JVM中
  • RetentionPolicy.RUNTIME,注解在任何阶段都会被保留。
@Target

@Target可以指定注解的使用范围,当注解未指定Target值时,注解可以用于任何元素之上

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
}
  • ElementType.TYPE,作用于类,接口(包括注解),枚举
  • ElementType.FIELD,作用于属性
  • ElementType.METHOD,作用于方法
  • ElementType.PARAMETER,作用于方法的参数
  • ElementType.CONSTRUCTOR,作用于构造方法
  • ElementType.LOCAL_VARIABLE,作用于局部变量
  • ElementType.ANNOTATION_TYPE,作用于注解
  • ElementType.PACKAGE,作用于包
  • ElementType.TYPE_PARAMETER,作用于类型参数声明
  • ElementType.TYPE_USE,作用于类型使用声明
@Inherited

Inherited翻译过来是继承的意思,这个注解的意思是一个注解如果被@Inherited所注解,那么这个注解修饰的类的子类如果没有被其他注解所修饰,将会默认继承这个注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
package org.zj;

import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestAnnotation {
}



package org.zj;
@TestAnnotation
public class Dad {
}


package org.zj;

public class Son extends Dad{
}



package org.zj;

import java.lang.annotation.Annotation;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        Dad dad = new Dad();
        Annotation[] dadAnnotations = dad.getClass().getAnnotations();
        System.out.println("dad的注解为"+ Arrays.toString(dadAnnotations));
        Son son = new Son();
        Annotation[] sonAnnotations = son.getClass().getAnnotations();
        System.out.println("son的注解为"+Arrays.toString(sonAnnotations));

    }
}

输出结果:
dad的注解为[@org.zj.TestAnnotation()]
son的注解为[@org.zj.TestAnnotation()]
@Repeatable

可重复的,被@Repeatable修饰的注解可以重复使用,如果没有@Repeatable,我们以前一般是这样来实现的,假设一个人有多重身份,我们可以在注解中定义一个数组

package org.zj;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Role {
    String[] value();
}


package org.zj;
@Role({"医生","儿子","父亲"})
public class Person {
}

当有了@Repetable我们可以用以下方式实现

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Roles {
    Role[] value();
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Roles.class)
public @interface Role {
    String value();
}


@Role("医生")
@Role("儿子")
@Role("父亲")
public class Person {
}

在这里Roles相当于一个容器注解,我们将使用Roles注解作为接收同一个类型上重复注解的容器

注解支持的数据类型
  • 八大基本数据类型
  • String
  • Class
  • enum
  • Annotation
  • 以上类型数组
public @interface LogAnnotation {
    
    //注解的属性默认值不能为Null
    //定义一个枚举
    enum TestEnum{SUCCESS,FAIL}
    
    int value();

    String name();

    //枚举类型
    TestEnum status() default TestEnum.SUCCESS;

//Class类型
    Class<?> testClass();
    //注解嵌套
    TestAnnotation testAnnotation() default @TestAnnotation;
    //数组
    String[] stringArray();
}
Java内置注解
  • @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();
}

deprecation:使用了不赞成使用的类或方法时的警告;
unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 
fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
path:在类路径、源文件路径等中有不存在的路径时的警告; 
serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告; 
finally:任何 finally 子句不能正常完成时的警告; 
all:关于以上所有情况的警告。
如何在开发中使用注解

相信看到这里的读者们都应该对注解有一个简单的了解,也会简单的定义一个注解,可是光定义一个注解好像也没啥用,甚至不如注释呢,要想使用注解,离不开一个必要的手段就是反射。

注解的常用方法
返回值方法名称说明
getAnnotation(Class annotationClass)如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。
Annotation[]getAnnotations()返回此元素上存在的所有注解。
Annotation[]getDeclaredAnnotations()返回直接存在于此元素上的所有注解。
booleanisAnnotation()如果此 Class 对象表示一个注解类型则返回 true。
booleanisAnnotationPresent(Class<? extends Annotation> annotationClass)如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。
package org.zjj;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface TestAnnotation {
}



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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AnnotationB {
}



package org.zjj;
@TestAnnotation
public class Fu {
}



import java.lang.annotation.Annotation;
import java.util.Arrays;
@AnnotationB
public class Zi extends Fu{
    public static void main(String[] args) {
        //返回此元素上存在的所有注解
        Zi zi = new Zi();
        Annotation[] annotations = zi.getClass().getAnnotations();
        System.out.println("此元素上存在的所有注解"+Arrays.toString(annotations));

        //获取直接存在此元素上的注解
        Annotation[] declaredAnnotations = zi.getClass().getDeclaredAnnotations();
        System.out.println("此元素直接存在的所有注解"+Arrays.toString(declaredAnnotations));

        //返回指定的注解,如果不存在,在返回Null
        AnnotationB annotation = zi.getClass().getAnnotation(AnnotationB.class);
        System.out.println("获取此类上的指定注解"+annotation);

        //判断此对象是否为一个注解对象
        boolean annotation1 = zi.getClass().isAnnotation();
        System.out.println("判断此对象是否为一个注解对象"+annotation1);

        //判断指定的注解是否存在此元素上
        boolean annotationPresent = zi.getClass().isAnnotationPresent(AnnotationB.class);
        System.out.println("判断指定的注解是否存在此元素上"+annotationPresent);
    }
}




此元素上存在的所有注解[@org.zjj.TestAnnotation(), @org.zjj.AnnotationB()]
此元素直接存在的所有注解[@org.zjj.AnnotationB()]
获取此类上的指定注解@org.zjj.AnnotationB()
判断此对象是否为一个注解对象false
判断指定的注解是否存在此元素上true
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值