Java annotation浅析

自定义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 [email protected]
 *
 */
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浅析

时间: 2024-10-24 05:56:11

Java annotation浅析的相关文章

自己写的基于java Annotation(注解)的数据校验框架

JavaEE6中提供了基于java Annotation(注解)的Bean校验框架,Hibernate也有类似的基于Annotation的数据校验功能,我在工作中,产品也经常需要使 用数据校验,为了方便和重用,自己写了一个简单的基于Annotation的校验框架.有兴趣的可以扩展. 框架说明: AnnotationValidable接口:所有需要使用该校验框架的类都要实现它,该类中没有任何方法需要实现,仅仅是一个表明那些类需要使用该校验框架的标识. GetFiledValue类:是一个工具类,对

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

PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示例 Override Annotation Java 1 2 3 @Override public void onCreate(Bundle savedInstanceState); Retrofit Annotation Java 1 2 3 @GET("/users/{username}&quo

第17篇-JAVA Annotation 注解

第17篇-JAVA Annotation 注解 每篇一句 :真的努力后你会发现自己要比想象的优秀很多 初学心得: 怀着一颗奋斗不息的心,一切困苦艰辛自当迎刃而解 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-05-17| JAVA Annotation注解 ] 1.什么是注解(Annotation) Annotation 其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行.在Java技术

1.2.4 Java Annotation 提要

(本文是介绍依赖注入容器Spring和分析JUnit源码的准备知识) Java Annotation(标注) java.lang.annotation.Annotation是全部Java标注的父接口.它除了override/改写Object的equals(Object).hashCode()和toString()外,仅有一个方法 Class<? extends Annotation> annotationType() 返回本标注的的类型. JDK中定义的标注java.lang.Override

学习笔记之Java Annotation学习总结 [ 光影人像 东海陈光剑 的博客 ]

?? 按照自己定的学习计划,今天是该写点什么了. ? 在上篇文章里提到的是JUnit的学习,其中就涉及到了一些内置的annotation,如@Test.@Ignore等.现在我就结合个人的理解谈下如何自定义自己的annotation. ? annotation能被用来为某个程序元素(类.方法.成员变量等)关联任何的信息,但annotaion不能影响程序代码的执行,无论增加.删除annotation,代码都始终如一的执行.另外,尽管一些annotation通过java的反射api方法在运行时被访问

Java Annotation原理分析(一)

转自:http://blog.csdn.net/blueheart20/article/details/18725801 小引: 在当下的Java语言层面上,Annotation已经被应用到了语言的各个方面,它已经在现在的ssh开发中,通过Annotation极大的提高了开发的效率,堪称开发神器.在这篇文章中,我们来了解一下的Annotation在Java中的前身今世吧. 1.   Java Annotation因何而来? 最初从印象中,是可以替代之前JDK1.4开发中,大量繁琐的配置项,Ann

Java Annotation 注解

java_notation.html div.oembedall-githubrepos { border: 1px solid #DDD; list-style-type: none; margin: 0 0 10px; padding: 8px 10px 0; font: 13.34px/1.4 helvetica, arial, freesans, clean, sans-serif; width: 452px; background-color: #fff } div.oembedall

Java Annotation入门

Java Annotation入门作者:cleverpig 版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)原 文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/arti

Java 内部类浅析

一.引言 由于目前是Android开发的实习生,在开发过程中发现越来越多自己知道但是真正去使用的时候却用不上的情况,比如内部类的使用上,所以在经过网上查找资料学习以及自己总结之后,特此发表一篇博文与大家分享,如有不当之处,万望指出. 二.内部类 内部类是指在一个外部类的内部再定义一个类,是一个编译时的概念,一旦编译成功,内部类与其外部类就会成为完全不同的两类,只是内部类的前面会冠以外部类的类名和$符号,如一个outer类内部定义了一个inner的内部类,那么编译完成后会生成outer.class