一、注解定义

JVM5.0定义了4个标准的元注解:

  • @Target,
  • @Retention,
  • @Documented
  • @Inherited

1. @Target

作用:用于描述注解的使用范围

取值ElementType有:

  • CONSTRUCTOR:用于描述构造器
  • FIELD:用于描述域
  • LOCAL_VARIABLE:用于描述局部变量
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述参数
  • TYPE:用于描述类、接口(包括注解类型) 或enum声明

举例:

@Target(ElementType.TYPE)
public @interface Table {
/**
* 数据表名称注解,默认值为类名称
* @return
*/
public String tableName() default "className";
} @Target(ElementType.FIELD)
public @interface NoDBColumn { }

注解Table可以用于注解类、接口(包括注解类型)或enum声明,而注解NoDBColumn仅用于注解类的成员变量。

2. @Retention

作用:用于描述注解的生命周期

取值RetentionPolicy有:

  • SOURCE:在源文件中有效(即源文件保留)
  • CLASS:在class文件中有效(即class保留)
  • RUNTIME:在运行时有效(即运行时保留)

举例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
public String name() default "fieldName";
public String setFuncName() default "setField";
public String getFuncName() default "getField";
public boolean defaultDBValue() default false;
}

Column注解的的RetentionPolicy的属性值是RUNTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

3. Documented

作用:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

举例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
public String name() default "fieldName";
public String setFuncName() default "setField";
public String getFuncName() default "getField";
public boolean defaultDBValue() default false;
}

4. @Inherited

@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

注意:Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

当Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层

实例代码:

@Inherited
public @interface Greeting {
public enum FontColor{ BULE,RED,GREEN};
String name();
FontColor fontColor() default FontColor.GREEN;
}

5. 自定义注解

  • 使用interface自定义注解,自动继承java.lang.annotation.Annotation接口。
  • 不能继承其他的注解或接口。
  • 每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(只能是基本类型、Class、String、enum)。可以通过default声明参数的默认值。

定义注解格式:

public @interface 注解名(定义体)

注解参数的可支持数据类型:

  • 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上所有类型的数组

自定义注解的定义和具体实现可以见下一章节。

二、注解实现

创建注解处理器,利用反射对注解加以处理。

AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,关于AnnotatedElement点详细信息可以参考

JavaDoc:Interface AnnotatedElement

所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

  • 方法1:
<T extends Annotation> T getAnnotation(Class<T> annotationClass):

返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

  • 方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。

  • 方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.

  • 方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

举例:

注解声明

1.FruitName

package annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}

2.FruitColor

package annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
public enum Color{BlUE, RED, GREEN};
Color fruitColor() default Color.GREEN; }

3.FruitProvider

package annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
public int id() default -1;
public String name() default "";
public String address() default "";
}

注解使用

package annotation;

import annotation.FruitColor.Color;

public class Apple {
@FruitName("Apple")
private String appleName; @FruitColor(fruitColor=Color.RED)
private String appleColor; @FruitProvider(id=1, name="红富士集团", address="红富士大厦")
private String appleProvider; public String getAppleName() {
return appleName;
} public void setAppleName(String appleName) {
this.appleName = appleName;
} public String getAppleColor() {
return appleColor;
} public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
} public String getAppleProvider() {
return appleProvider;
} public void setAppleProvider(String appleProvider) {
this.appleProvider = appleProvider;
} public void display(){
System.out.println("The fruit name is:" + appleName + ", its color is: " + appleColor + ".");
} }

注解实现

package annotation;

import java.lang.reflect.Field;

public class FruitInfoUtil {
public static void getFruitInfo(Class<?> clazz){
String strFruitName= "水果名称: ";
String strFruitColor= "水果颜色: ";
String strFruitProvider= "供应商信息: "; Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){
if (field.isAnnotationPresent(FruitName.class)){
FruitName fruitName = (FruitName)field.getAnnotation(FruitName.class);
strFruitName += fruitName.value();
System.out.println(strFruitName);
} if (field.isAnnotationPresent(FruitColor.class)){
FruitColor fruitColor = (FruitColor)field.getAnnotation(FruitColor.class);
strFruitColor += fruitColor.fruitColor().toString();
System.out.println(strFruitColor);
} if (field.isAnnotationPresent(FruitProvider.class)){
FruitProvider fruitProvider = (FruitProvider)field.getAnnotation(FruitProvider.class);
strFruitProvider += " 供应商编号:" + fruitProvider.id() + " 供应商名称:" + fruitProvider.name() + " 供应商地址:" + fruitProvider.address();
System.out.println(strFruitProvider);
}
}
}
}

执行结果:

水果名称: Apple
水果颜色: RED
供应商信息: 供应商编号:1 供应商名称:红富士集团 供应商地址:红富士大厦

三、注解基础知识点汇总

四、参考博客

  1. 深入理解Java:注解
  2. Java技术之反射
  3. Java技术之注解

Java注解学习的更多相关文章

  1. java 注解 学习

    周末闲来无事,想要研究一下注解方面的知识,曾经看过几次,都忘记了,这次学习下,而且写篇文章记录下, 1.元注解  元注解是指注解的注解.包含 @Retention @Target @Document ...

  2. Java注解学习笔记

    我们平常写Java代码,对其中的注解并不是很陌生,比如说写继承关系的时候经常用到@Override来修饰方法.但是@Override是用来做什么的,为什么写继承方法的时候要加上它,不加行不行.如果对J ...

  3. java注解学习(1)注解的作用和三个常用java内置注解

    今天,记录一下自己学习的关于注解方面的知识. Annotation是从JDK5.0开始引入的新技术 Annotation的作用: -不是程序本身,可以对程序做出解释(这一点和注释没什么区别) -可以被 ...

  4. [JAVA] 注解学习@interface

    一直都看框架级的代码中都是各种annotation,一起来看看到底怎么弄的 例子1:直接定义一个annotation,并使用之: package com.base.annotation.example ...

  5. java注解学习笔记总结

    注解的理解 ① jdk 5.0 新增的功能 ② Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理.通过使用 Annotation,程序 ...

  6. java注解使用总结

    2005年,sun公司推出了jdk1.5,同时推出的注解功能吸引了很多人的目光,使用注解编写代码,能够减轻java程序员繁琐配置的痛苦. 使用注解可以编写出更加易于维护,bug更少的代码. 注解是什么 ...

  7. Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 本文是Java反射学习总结系列的最后一篇了,这里贴出之前文章的链接,有兴趣的可以打开看看. ...

  8. 深入学习JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  9. Java注解系统学习与实战

    背景 为什么要再次梳理一下java注解,显而易见,因为重要啊.也是为研究各大类开源框架做铺垫,只有弄清楚Java注解相关原理,才能看懂大部分框架底层的设计. 缘起 注解也叫做元数据,是JDK1.5版本 ...

随机推荐

  1. jumpserver在centos 7上的部署

    cd /opt/git clone https://github.com/jumpserver/jumpserver.gitcd jumpservergit checkout master 准备安装: ...

  2. centos7设置静态ip

    动态ip可以上网.静态ip设置成功后,发现不能上网. 1.首先查看动态ip的默认网关 cat /etc/resolv.conf 2.设置配置文件 在 /etc/sysconfig/network-sc ...

  3. php获取今日开始时间戳和结束时间戳

    1.php获取今日开始时间戳和结束时间戳  $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y'));$endToday=mktime(0,0,0 ...

  4. Linux 安装配置 FTP 服务 (vsftpd)

    1. 安装 vsftpd yum install vsftpd -y 2. 创建用户 record adduser -s /bin/nologin -d /var/RecordFile/ record ...

  5. ajaxfileupload批量上传文件+图片尺寸限制

    1.首先展示ajaxfileupload代码,在这里修改为批量上传 //ajaxfileupload不展示全部代码,这是修改前与修改后代码对比,目的是上传多个文件 createUploadForm: ...

  6. Java经典编程题50道之三十五

    有一个数组,将其最大的元素与第一个元素交换,最小的元素与最后一个元素交换,然后输出数组. public class Example35 {    public static void main(Str ...

  7. Shell脚本的基本流程控制

    if else read -p '请输入分数:' score if [ $score -lt 60 ]; then echo '60分以下' elif  [ $score -lt 70 ]; then ...

  8. CompletableFuture CompletableFuture.supplyAsync 异常处理

    CompletableFuture 异常处理completeExceptionally可以把异常抛到主线程 /** * User: laizhenwei * Date: 2018-01-30 Time ...

  9. Activity的生命周期& 启动模式

    1.Activity的生命周期 生命周期这个事情,是android工程师最基础的知识,所以今天要讲的是一些不一样的东西. 1.1 OnStart,OnResume,OnPause,OnStop 他们的 ...

  10. 分享一个Appium/selenium测试报告模板

    介绍 这个模板改编自 这位外国老哥 效果图 错误截图 录像 失败的case可以点击"view"查看报错信息, 也可以点击screenshot查看截图信息,更可以点击replay查看 ...