美文网首页
Java注解详解

Java注解详解

作者: 阿龙的学与思 | 来源:发表于2018-10-07 21:25 被阅读0次

虽然在平时开发中经常使用注解,却不知道如何自定义一个注解类型以及注解的实现原理。抽时间学习了一下,记录下来加深理解。

1. 注解是什么

之前看到一篇文章将注解理解为“标签”,感觉还是比较贴切的。我们可以把注解理解为给包、类、方法、字段打的一个标签,并利用java的反射机制对注解标注的类、方法或者字段进行相应的处理。

2. 定义注解

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface AnnotationDemo {
    String name() default "";
}

利用关键字@interface声明一个注解类型,并利用@Retention、@Target、@Document、@Inherited等元注解对注解进行定义。

  • @Retention
    用于自定义注解类型的元注解。retention的意思是保留,@Retention用来定义自定义注解有效期。有三种取值:
public enum RetentionPolicy {
    /**
     * 注解只在源码文件中保留,不会被编译器编译
     */
    SOURCE,

    /**
     * 会被编译到生成的class文件中,但不会在运行时保留
     */
    CLASS,

    /**
     * 运行时有效,可以通过反射机制读取到该注解定义
     */
    RUNTIME
}
  • @Target
    用于定义注解的使用目标。我们知道注解可以用在包、类、方法、字段等字面量上,但不能将类的注解用到方法上,JDK使用@Target定义注解的使用目标。在java.lang.annotation.ElementType 枚举类型中定义了若干注解目标枚举常量:TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE等。
    ElementType.TYPE 用于定义类、接口、枚举注解;
    ElementType.METHOD 用于定义方法注解;
    ElementType.FIELD 用于定义字段注解;
    ElementType.CONSTRUCTOR 用于定义构造器注解;
  • @Document
    这个元注解比较简单,用于将该注解包含在Javadoc中
  • @Inherited
    在定义注解时加上@Inherited表示该注解具有"继承性",这里的继承性是指如果父类使用了自定义注解,则子类也继承了该自定义注解。举例说明:
/**
 * 自定义注解AnnotationDemo、使用@Inherited表明该注解注解具有继承性
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface AnnotationDemo {
    String name() default "";
}
/**
 * 使用自定义注解修饰的父类
 */
@AnnotationDemo(name = "小明")
public class Super {
    public void hello(){
        System.out.println("I am super!");
    }
}
/**
 * 子类继承Super超类
 * 由于Super被@AnnotationDemo注解修饰,Child子类自动被@AnnotationDemo修饰,
 *
 */
public class Child extends Super {
    public void say(){
        System.out.println("I am child!");
    }
}

3. 注解的属性

在自定义注解时可以为注解定义若干属性,如在上边定义的@AnnotationDemo注解中定义了一个名为name的属性,默认值为""。注解类型只有属性没有方法,且注解属性声明为属性名+(),属性类型可以为基本类型、String、Class、Enum等类型。注解的属性使用default关键字声明该属性的默认值,如果不为属性声明默认值,则必须在使用注解时为该属性赋值。
特殊的:如果属性名为value,在使用注解时可以不指定属性名赋值。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface AnnotationDemo {
    String value() default "";
}
/**
 * @AnnotationDemo注解的属性名为value,使用时可以不指定属性名为属性赋值
 * 等价于@AnnotationDemo(value="super")
 */
@AnnotationDemo("super")
public class Super {
    public void hello(){
        System.out.println("hello world!");
    }
}

如果注解定义了多个属性,使用时不同的属性赋值用逗号分隔。

4. 注解与反射

正如在本文开头所说的注解相当于给类、方法、字段打的标签,对于运行时有效的注解需要通过JDK提供的反射机制来让标签起作用。下面通过一个简单的例子来演示如何利用反射机制使注解起作用。

  • 自定义一个注解@Run
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Run {
    
}
  • 使用定义的注解标注方法
public class RunTest {
    @Run
    public void test1(){
        System.out.println("run test1");
    }

    public void test2(){
        System.out.println("run test2");
    }
}
  • 通过反射API对@Run标记的方法执行调用
public class Main {

    public static void main(String[] args) throws ClassNotFoundException{
        try {
            Class clazz = Class.forName("com.annotation.demo.test.RunTest");
            Method[] methods = clazz.getMethods();
            RunTest junitTest =(RunTest) clazz.newInstance();
            for (Method method : methods){
                if (method.isAnnotationPresent(Run.class)){
                    method.setAccessible(true);
                    method.invoke(junitTest);
                }
            }
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }catch (InstantiationException e){
            e.printStackTrace();
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }catch (InvocationTargetException e){
            e.printStackTrace();
        }
    }
}

在这个例子中首先定义了一个@Run注解,并在RunTest中定义了两个方法。其中一个方法使用了@Run进行注解,另一个方法没有添加@Run注解,利用反射API对使用了@Run注解的方法进行调用。输出结果也正如我们所料:只有RunTest中的test1方法被执行。

OK,java注解的介绍就到这里。

你的关注是我持续更新的动力!

相关文章

  • Java注解

    Java注解(Annotation)详解(一)——概述及JDK自带注解 Java注解(Annotation)详解(...

  • Android 编译时注解 —— 语法详解

    java Type 详解 java 反射机制详解 注解使用入门(一) Android 自定义编译时注解1 - 简单...

  • 详解Java注解( Annotation )

    详解Java注解( Annotation ) 注解的定义: 注解(Annotation),也叫元数据。一种代码级别...

  • Java注解笔记

    Java注解详解 Java注解是JDK1.5以后添加的特性,自定义注解需要声明为@interface。 最简单的注...

  • Java注解(Annotation)详解

    Java注解(Annotation)详解 1.Annotation的概念 An annotation is a f...

  • Java注解 + 基于注解 & 拦截器实现登录验证 /

    Java中的注解是如何工作的?java 注解的几大作用及使用方法详解一种基于注解的Spring MVC权限控制方法...

  • Java注解详解

    虽然在平时开发中经常使用注解,却不知道如何自定义一个注解类型以及注解的实现原理。抽时间学习了一下,记录下来加深理解...

  • java注解详解

    介绍 java 1.5引入了注解(annotation),注解类似注释,不同的是注解除了提供代码说明,还能实现程序...

  • Java注解详解

    Annotation基础 1、什么是annotation 官网的解释: Annotations, a form o...

  • Java注解详解

    2.5 注解 2.5.1 注解简介 Annotation是Java提供的一种元程序中的元素关联任何信息和元数据(m...

网友评论

      本文标题:Java注解详解

      本文链接:https://www.haomeiwen.com/subject/gmtroftx.html