一、注解定义

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. 【应知应会】15个常用的JavaScript字符串操作方法

    1 初始化 //常用初始化方法 var stringVal = "hello iFat3"; //构造函数创建方法 var stringObj = new String(" ...

  2. EF数据迁移,未将对象引用设置到对象实例

    现象: 执行Enable-Migrations -force时就报"未将对象引用设置到对象实例"的异常: DbProviderServicesExtensions.GetProvi ...

  3. 注册表命令 regedit32

    转自 https://zhidao.baidu.com/question/1958216489744783460.html Regedt32.exe 不支持注册表项文件 (.reg) 的导入和导出. ...

  4. C语言_简单了解一下typedef

    作为一名PHPer,了解一下C还是有必要的,只是做一个简单的了解,因为并没有做开发C的想法. 关于typedef的详细说明,网上搜过了很多帖子,这篇算是最详细的了:http://blog.csdn.n ...

  5. AES-256加密解密

    /// <summary> /// AES-256加密 /// </summary> /// <param name="toEncrypt">& ...

  6. 单例模式,堆,BST,AVL树,红黑树

    单例模式 第一种(懒汉,线程不安全): public class Singleton { private static Singleton instance; private Singleton () ...

  7. gitlab启用https

    为了防止内网渗透,将gitlab服务的访问添加了ssl,具体步骤如下: 修改配置文件 [xieshuang@VM_177_101_centos gitlab]$ sudo vim /etc/gitla ...

  8. 使用tcpcopy导入线上流量进行功能和压力测试

    - 假设我们要上线一个两年内不会宕机的先进架构.在上线前,免不了单元测试,功能测试,还有使用ab,webbench等等进行压力测试. 但这些步骤非生产环境下正式用户的行为.或许你会想到灰度上线,但毕竟 ...

  9. 普通权限拿webshell

    普通权限拿webshell:   1.0day拿webshell:这个不多说.可以去网上搜索一些, 比如你找到你搞的网站cms是discz的,你可以搜索一些相 关0day直接拿   2.修改网站上传类 ...

  10. 实战DeviceIoControl 之六:访问物理端口

    Q 在NT/2000/XP中,如何读取CMOS数据? Q 在NT/2000/XP中,如何控制speaker发声? Q 在NT/2000/XP中,如何直接访问物理端口? A 看似小小问题,难倒多少好汉! ...