Java魔法堂:自定义和解析注解

一、前言                            

  注解(Annotation)作为元数据的载体,为程序代码本身提供额外的信息,使用过MyBatis等ORM框架的朋友对 @Insert 的注解应该不陌生了,这是MyBatis自定义的注解,显然我们也可以按需求自定义一些注解,然后对其进行解析获取元数据,进而实现通过代码生成代码的操作。

 

二、自定义注解                         

 只需通过 关键字@interface 即可自定义注解

// 标识注解(就是无属性的注解)
public @interface AnnotationWithoutProperty{
}

// 带value属性的注解
public @interface AnnotationWithVal{
  String value();
}

// 带myVal属性的注解
public @interface AnnotationWithMyVal{
  String[] myValue();
}

// 带value和myVal属性的注解
public @interface AnnotationWith2Val{
  String value();
  String[] myValue();
}

// 带缺省值的myVal属性的注解
public @interface AnnotationWithDefaultVal{
  String myVal() default "hello world!";
}

使用方式如下:

@AnnotationWithoutProperty
@AnnotationWithVal("hello world") // value属性赋值时,不用显式写出属性名
@AnnotationWithMyVal(myValue={"hello", "world"}) // 其他属性赋值时,必须显示写出属性名
@AnnotationWith2Val(value="hello world", myVal={"hello", "world"})
@AnnotationWithDefaultVal // 属性拥有缺省值时,不必显示设置属性值
@AnnotationWithDefaultVal("new value")
public void test(){}

三、注解的注解                              

  注解的注解就是为注解本身提供额外的信息,从而约束或增强注解的能力。其中包含有 @Documented 、 @Inherited 、 @Target 、 Retention 4种注解。

   @Target注解 :用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败。


// 约束@MyAnnotation的作用范围是函数和构造函数
@Target(ElementType.METHOD, ElementType.CONSTRUCTOR)
public @interface MyAnnotation{}

   @Retention注解 :用于约束被描述的注解的作用范围,注解的作用范围有三个,分别为

        1.  RetentionPolicy.SOURCE ,作用范围为源码,就是仅存在于java文件中,当执行 javac 命令时将会去除该注解。

        2.  RetentionPolicy.CLASS ,作用范围为二进制码,就是存在于class文件中,当执行 java 命令时会去除该注解。

        3.  RetentionPolicy.RUNTIME ,作用范围为运行时,就是我们可以通过反射动态获取该注解。

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{}

    @Documented注解 :用于指定javadoc生成API文档时显示该注解信息

    @Inherited注解 :用于指定被描述的注解可以被其所描述的类的子类继承。默认情况

// 默认注解不会被子类继承
@MyAnnotation
public class Parent{}

// Son并没有继承注解MyAnnotation
public class Son extends Parent{}

通过 @Inherited 子类将会继承父类的 @MyAnnoation注解 。

 

四、读取注解                                  

  通过反射我们可以获取类、函数等上的注解信息。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CLASS)
@Documented
public @interface MyAnnotaion{
  String value() default "hello world";
}

@MyAnnotation
public class Test{
  public static void main(String[] args){
    MyAnnotation ma = Test.class.getAnnotation(MyAnnotation.class);
    System.out.println(ma.value());

    // 获取自身和从父类继承的注解
    Annotation[] annotations = Test.class.getAnnotations();
    // 仅获取自身的注解
    Annotation[] annotations = Test.class.getDeclaredAnnotations();
  }
}
时间: 2024-09-12 09:32:57

Java魔法堂:自定义和解析注解的相关文章

Java魔法堂:类加载器入了个门

一.前言   <Java魔法堂:类加载机制入了个门>中提及整个类加载流程中只有加载阶段作为码农的我们可以入手干预,其余均由JVM处理.本文将记录加载阶段的核心组件--类加载器的相关信息,以便日后查阅.若有纰漏请大家指正,谢谢.   注意:以下内容基于JDK7和HotSpot VM.   二.类加载器种类及其关系 从上图可知Java主要有4种类加载器 1. Bootstrap ClassLoader(引导类加载器):作为JVM的一部分无法在应用程序中直接引用,由C/C++实现(其他JVM可能通过

Java魔法堂:打包知识点之jar

一.前言      通过eclipse导出jar包十分方便快捷,但作为码农岂能满足GUI的便捷呢?所以一起来CLI吧!   二.JAR包   JAR包是基于ZIP文件格式,用于将多个.java文件和各种资源文件,或将多个.class和各种资源打包为一个文件.用于发布,部署,封装库.组件和插件程序,从而被编译器和JVM使用.   三.通过jar命令打包     1. 格式 jar [option]* 文件名        必选选项(并且仅能选用其中一个)        -c ,创建一个jar包  

Java魔法堂:注解用法详解——@SuppressWarnings

一.前言   编码时我们总会发现如下变量未被使用的警告提示:   上述代码编译通过且可以运行,但每行前面的"感叹号"就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWarnings("unused") 去除这些"感叹号".   二. @SuppressWarings注解    作用:用于抑制编译器产生警告信息.   示例1--抑制单类型的警告: @SuppressWarnings("unchecke

Java魔法堂:注解用法详解——@SuppressWarnings(转)

一.前言   编码时我们总会发现如下变量未被使用的警告提示:   上述代码编译通过且可以运行,但每行前面的"感叹号"就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWarnings("unused") 去除这些"感叹号".   二. @SuppressWarings注解    作用:用于抑制编译器产生警告信息.   示例1--抑制单类型的警告: @SuppressWarnings("unchecke

Java魔法堂:注解用法详解——@Override

一.前言   现在有Son和Parent两个类,且类型Son将会重写类型Parent的getName函数.但不幸的是由于码农大意,写成如下代码: public class Parent{ public String getName(){ return "Parent"; } } public class Son extends Parent{ public String getNames(){ return "Son"; } }  上述代码编译通过且人工无意识到实现

Java魔法堂:Date与日期时间格式化

一.前言                                                                                           日期时间的获取.显示是每个程序都会涉及到的,下面是一些记录以便日后查阅.   二. java.util.Date类  // 当前日期时间 Date now = new Date(); /* 由于程序的默认时区不同,可能显示如下内容: * 1. 格林尼治时间,Tue Oct 28 01:24:14 GMT 20

Java魔法堂:枚举类型详解

一.前言   Java的枚举类型相对C#来说具有更灵活可配置性,Java的枚举类型可以携带更多的信息. // C# enum MyColor{ RED = 0, BLUE = 1 } Console.Write(MyColor.RED); // Java enum MyColor{ RED("Hot", 4), BLUE("SAD",8); private String mood; public String getMood{ return mood; } priv

Java魔法堂:URI、URL(含URL Protocol Handler)和URN

一.前言   过去一直搞不清什么是URI什么是URL,现在是时候好好弄清楚它们了!本文作为学习笔记,以便日后查询,若有纰漏请大家指正!   二.从URI说起    1. 概念   URI(Uniform Resource Identifier,统一资源标识符)以字符串来表示某种资源的统一资源标识.   格式为: [scheme:]scheme-specific-part[#fragment]    [scheme:]组件 ,URI的名称空间标识.   scheme-specific-part组件

Java魔法堂:类加载机制入了个门

一.前言   当在CMD/SHELL中输入 $ java Main<CR><LF> 后,Main程序就开始运行了,但在运行之前总得先把Main.class及其所依赖的类加载到JVM中吧!本篇将记录这些日子对类加载机制的学习心得,以便日后查阅.若有纰漏请大家指正,谢谢!   以下内容均基于JDK7和HotSpot VM.   二.执行java的那刻     大家都知道通过java命令来启动JVM和运行应用程序,但实际的流程又是如何的呢?   1. 首先根据java后的运行模式配置项或