自定义annotation

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
public @interface TestAnnotation {
    //default关键字是用来设置注解的默认值,可有可没有
    String value() default("Hello,I am a field");
    String [] name() default {};
}

使用自定义的annotation

public class HelloWorld {
   
    @TestAnnotation(name={"walson","ruby"})
    private String name;

//没有写明就表示value=“值”
    @TestAnnotation("hello")
    private String msg;

public String getName() {
        return name;
    }

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

public String getMsg() {
        return msg;
    }

public void setMsg(String msg) {
        this.msg = msg;
    }
    
    
    public static void main(String[] args) {
        
    }
}

annotation的解析

public class AnnotationRelolver{

public static void relolver(Class<?> clazz){
        for(Field field : clazz.getDeclaredFields()){
            TestAnnotation testAnnotation = field.getAnnotation(TestAnnotation.class);
            System.out.println(field.getName() + " 上注解的Value值: " + testAnnotation.value());
            
            StringBuilder stringBuilder = new StringBuilder("[");
            String[] names = testAnnotation.name();
            int count = 0;
            for(String str : names){
                stringBuilder.append(str);
                count ++ ;
                if(count < names.length){
                    stringBuilder.append(",");
                }
                
                
            }
            stringBuilder.append("]");
            System.out.println(field.getName() + " 上注解的name值: " + stringBuilder.toString());
        }    
    }
    
    public static void main(String[] args) {
        AnnotationRelolver.relolver(HelloWorld.class);
    }
}

annotation源码分析

jdk1.5引入了annotation包,位于java.lang.annotation包下:

Annotation

package java.lang.annotation;

public interface Annotation {
 
    boolean equals(Object obj);

int hashCode();

String toString();
  //返回此 annotation 的注释类型
    Class<? extends Annotation> annotationType();
}

1.所有自定义的注解都默认的继承这接口

ElementType

public enum ElementType {

  //类,接口,枚举声明
    TYPE,
  //字段声明
    FIELD,
  //方法声明
    METHOD,
  //参数声明
    PARAMETER,
  //构造方法声明
    CONSTRUCTOR,
  //局部变量声明
    LOCAL_VARIABLE,
  //注解类型声明
    ANNOTATION_TYPE,
  //包声明
    PACKAGE,

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

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

这个枚举类主要用来定义注解可以声明在那些元素上

RetentionPolicy

package java.lang.annotation;

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

   * 注解只保留在源码中即*.java文件中,编译成class文件时将被废弃
     */
    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.

     * 注解保留在源码中即*.java与class文件中,VM运行时将不被保留,默认为class
     */
    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.
     * 注解保留在源码中即*.java与class文件中,VM运行时也读取注解信息
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

这个枚举类用于声明注解的作用范围

Retention

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
这是jdk自定义的一注解类,其value方法主要用于第一注解类时设置注解的作用方法

Target

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

这个注解类主要用于声明注解可以声明在哪些元素上

Inherited

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

默认注解是不能继承的,即一注解注解在父类上,默认其子类是不能使用父类的注解的,但是如果在定义注解类时加上Inherited这个注解那么父类所有的注解将自动被之类继承下来

例如:

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

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

package com.jyz.study.jdk.reflect;

import java.util.Arrays;

import com.jyz.study.jdk.annotation.DBTable;
import com.jyz.study.jdk.annotation.DBTable2;

/**
 * 1.演示从Class对象上获得反射元素Field Method Constructor
 * 2.演示AnnotatedElement接口的四个方法
 * @author JoyoungZhang@gmail.com
 *
 */
public class DeclaredOrNot {

public static void main(String[] args) {
        Class<Sub> clazz = Sub.class;
        System.out.println("============================Field===========================");
        //public + 继承
        System.out.println(Arrays.toString(clazz.getFields()));
        //all + 自身
        System.out.println(Arrays.toString(clazz.getDeclaredFields()));
        
        System.out.println("============================Method===========================");
        //public + 继承
        System.out.println(Arrays.toString(clazz.getMethods()));
        //all + 自身
        System.out.println(Arrays.toString(clazz.getDeclaredMethods()));
        
        System.out.println("============================Constructor===========================");
        //public + 自身
        System.out.println(Arrays.toString(clazz.getConstructors()));
        //all + 自身
        System.out.println(Arrays.toString(clazz.getDeclaredConstructors()));
        
        
        System.out.println("============================AnnotatedElement===========================");
        //注解DBTable2是否存在于元素上
        System.out.println(clazz.isAnnotationPresent(DBTable2.class));
        //如果存在该元素的指定类型的注释DBTable2,则返回这些注释,否则返回 null。
        System.out.println(clazz.getAnnotation(DBTable2.class));
        //继承
        System.out.println(Arrays.toString(clazz.getAnnotations()));
        //自身
        System.out.println(Arrays.toString(clazz.getDeclaredAnnotations()));
    }
}

@DBTable
class Super{
    private int superPrivateF;
    public int superPublicF;
    
    public Super(){
    }
    
    private int superPrivateM(){
        return 0;
    }
    public int superPubliceM(){
        return 0;
    }
}

@DBTable2
class Sub extends Super{
    private int subPrivateF;
    public int subPublicF;
    
    private Sub(){
    }
    public Sub(int i){
    }
    
    private int subPrivateM(){
        return 0;
    }
    public int subPubliceM(){
        return 0;
    }
}

console output:
============================Field===========================
[public int com.jyz.study.jdk.reflect.Sub.subPublicF, public int com.jyz.study.jdk.reflect.Super.superPublicF]
[private int com.jyz.study.jdk.reflect.Sub.subPrivateF, public int com.jyz.study.jdk.reflect.Sub.subPublicF]
============================Method===========================
[public int com.jyz.study.jdk.reflect.Sub.subPubliceM(), public int com.jyz.study.jdk.reflect.Super.superPubliceM(), public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
[private int com.jyz.study.jdk.reflect.Sub.subPrivateM(), public int com.jyz.study.jdk.reflect.Sub.subPubliceM()]
============================Constructor===========================
[public com.jyz.study.jdk.reflect.Sub(int)]
[private com.jyz.study.jdk.reflect.Sub(), public com.jyz.study.jdk.reflect.Sub(int)]
============================AnnotatedElement===========================
true
@com.jyz.study.jdk.annotation.DBTable2(name=)
[@com.jyz.study.jdk.annotation.DBTable(name=), @com.jyz.study.jdk.annotation.DBTable2(name=)]
[@com.jyz.study.jdk.annotation.DBTable2(name=)]

Repeatable

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    /**
     * Indicates the <em>containing annotation type</em> for the
     * repeatable annotation type.
     * @return the containing annotation type
     */
    Class<? extends Annotation> value();
}

这个类是jdk1.8引入的

在1.8之前重复注解如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuthorityOldVersion {
    String role();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuthoritiesOldVersion {
    AuthorityOldVersion[] value();
}

public class RepeatAnnotationUseOldVersion {
    @AuthoritiesOldVersion({@AuthorityOldVersion(role="Admin"),@AuthorityOldVersion(role="Manager")})
    public void doSomeThing(){
    }
}

jdk1.8之后:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(AuthoritiesNewVersion.class)
public @interface AuthorityNewVersion {
    String role();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuthoritiesNewVersion {
    AuthorityNewVersion[] value();
}

public class RepeatAnnotationUseNewVersion {
    @AuthorityNewVersion(role="Admin")
    @AuthorityNewVersion(role="Manager")
    public void doSomeThing(){
    }
}

不同的地方是,创建重复注解Authority时,加上@Repeatable,指向存储注解Authorities,在使用时候,直接可以重复使用Authority注解。从上面例子看出,java 8里面做法更适合常规的思维,可读性强一点

Native

/**
 * Indicates that a field defining a constant value may be referenced
 * from native code.
 *
 * The annotation may be used as a hint by tools that generate native
 * header files to determine whether a header file is required, and
 * if so, what declarations it should contain.
 *
 * @since 1.8
 */
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Native {
}

具体可参考JEP 104 :Java类型注解,JEP 120 :重复注解,JSR 175: A Metadata Facility for the JavaTM Programming Language

Java annotation浅析的更多相关文章

  1. Java Annotation概述

    @(Java)[Annotation|Java] Java Annotation概述 用途 编译器的相关信息,如用于检测错误和一些警告 编译时和部署时的处理,如一些软件用于自动生成代码之类的 运行时处 ...

  2. Java Annotation 注解

    java_notation.html div.oembedall-githubrepos { border: 1px solid #DDD; list-style-type: none; margin ...

  3. paip.Java Annotation注解的作用and 使用

    paip.Java Annotation注解的作用and 使用 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog. ...

  4. Java Annotation认知(包括框架图、详细介绍、示例说明)

    摘要 Java Annotation是JDK5.0引入的一种注释机制. 网上很多关于Java Annotation的文章,看得人眼花缭乱.Java Annotation本来很简单的,结果说的人没说清楚 ...

  5. Java Annotation原理分析(一)

    转自:http://blog.csdn.net/blueheart20/article/details/18725801 小引: 在当下的Java语言层面上,Annotation已经被应用到了语言的各 ...

  6. Java Annotation 及几个常用开源项目注解原理简析

    PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示 ...

  7. Java Annotation 机制源码分析与使用

    1 Annotation 1.1 Annotation 概念及作用      1.  概念 An annotation is a form of metadata, that can be added ...

  8. Java Annotation手册

    Java Annotation手册 作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig) 原文:http://www.matri ...

  9. Java Annotation 必须掌握的特性

    什么是Annotation? Annotation翻译为中文即为注解,意思就是提供除了程序本身逻辑外的额外的数据信息.Annotation对于标注的代码没有直接的影响,它不可以直接与标注的代码产生交互 ...

随机推荐

  1. classPath与PATH

    PATH是window的变量,而不是Java的变量: 通常配置PATH路径是为了找到需要的XX.exe命令,而且配置在用户的变量下面: 例如:JDK中的javac与java命令在cmd中使用,需要把命 ...

  2. Hadoop学习------Hadoop安装方式之(一):单机部署

    Hadoop 默认模式为单机(非分布式模式),无需进行其他配置即可运行.非分布式即单 Java 进程,方便进行调试. 1.创建用户 1.1创建hadoop用户组和用户 一般我们不会经常使用root用户 ...

  3. wpf 依赖属性介绍

    微软在wpf中推出le 附加属性 这个新概念 简单来说,本来自己这个类是不具备该行为,但是在特殊情况下需要用到该属性 比如在 TextBox 本来是不具备,几行几列 跨行等 行为 ,但是如果  把他放 ...

  4. ElementUI - Table 表头排序

    ElementUI - Table 表头自带排序功能,和排序事件,但是目前只是对当前界面的数据进行排序. 项目需求: 点击表头排序的时候,对所有数据进行排序. 初步方案: 在点击排序按钮的时,在排序事 ...

  5. 剑指Offer 61. 序列化二叉树 (二叉树)

    题目描述 请实现两个函数,分别用来序列化和反序列化二叉树 题目地址 https://www.nowcoder.com/practice/cf7e25aa97c04cc1a68c8f040e71fb84 ...

  6. 如何生成SSH key及查看SSH key

    只适用于Mac和windows下的Git Bash操作界面. 一.检查本地是否有SSH Key存在 在终端输入 ls -al ~/.ssh 如果终端输出的是: No such file or dire ...

  7. Power BI 关注博客更新

    原本当你访问你常用的数据库时候,该库的新增,修改,删除,通过PowerBI都很容易发现,但是在Web上面,通过PowerBI来发现Web修改就没那么容易了. 现在,我想通过PowerBI的报告来显示某 ...

  8. mybatis 源码分析一

    1.SqlSessionFactoryBuilder  public SqlSessionFactory build(InputStream inputStream, String environme ...

  9. projects(好代码好工具)每天进步一点点

    1. 行人检测的,感觉这个代码不错,起码换个数据集测试也不错: https://bitbucket.org/shanshanzhang/code_filteredchannelfeatures 2. ...

  10. Tomcat生成的session持久化到MySQL

    Telling Tomcat to save session records in MySQL 此部分内容摘自 MySQL cookbook 3th.具体内容不做翻译,哈哈,懒 The default ...