从 jdk5开始,Java增加了对元数据的支持,也就是Annotation,Annotation其实就是对代码的一种特殊标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。当然刚刚说了,Annotation只是一种标记,所以要是在代码里面不用这些标记也是能完成相应的工作的,只是有时候用注解能简化很多代码,看起来非常的简洁。

常见的注解(Annotation)

@Override——限定重写父类方法

@Deprecated——标示已过时

@SuppressWarning——抑制编译器警告

JAVA的元注解

除了上面的注解,还有元注解。元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种。

1.@Retention 这个是决定你Annotation存活的时间的,它包含一个RetationPolicy的value成员变量,用于指定它所修饰的Annotation保留时间,一般有:

1. Retationpolicy.CLASS:编译器将把注解记录在Class文件中,

不过当java程序执行的时候,JVM将抛弃它。不过当java程序执行的时候,JVM将抛弃它。

2. Retationpolicy.SOURCE : 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得。

4. Retationpolicy.RUNTIME : 在Retationpolicy.CLASS的基础上,JVM执行的时候也不会抛弃它,所以我们一般在程序中可以通过反射来获得这个注解,然后进行处理。

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以MT4下载教程前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。

2.@Target 这个注解一般用来指定被修饰的注解修饰哪些元素,如下:

ElementType.ANNOTATION_TYPE : //注解

ElementType.CONSTRUCTOR: //构造函数

ElementType.FIELD: //字段、枚举的常量

ElementType.LOCAL_VARIABLE: //局部变量

ElementType.METHOD: //方法

ElementType.PACKAGE: //包

ElementType.PARAMETER://方法参数

ElementType.TYPE: //接口、类、枚举、注解

@Document 这个注解修饰的Annotation类可以被javadoc工具提取成文档

@Inherited 被他修饰的注解具有继承性,说明子类可以继承父类中的该注解

例子

自定义注解MyClassAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface MyClassAnnotation {

String value();

}

自定义注解MyFieldAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface MyFieldAnnotation {

public String name() default "fieldName";

}

自定义注解MyMethodAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface MyMethodAnnotation {

String name();

int age();

}

在实例中使用TestRuntimeAnnotation 来测试注解情况:

@MyClassAnnotation(value = "test Class")

public class TestRuntimeAnnotation {

@MyFieldAnnotation

public String fieldInfo = "FiledInfo";

@MyMethodAnnotation(age = 0, name = "zhangsan")

public static String getMethodInfo() {

return TestRuntimeAnnotation.class.getSimpleName();

}

public static void main(String[]args) {

StringBuffer sb = new StringBuffer();

Class<?> cls = TestRuntimeAnnotation.class;

sb.append("Class注解:").append("\n");

MyClassAnnotation myClassAnnotation = cls.getAnnotation(MyClassAnnotation.class);

if (myClassAnnotation != null) {

sb.append(Modifier.toString(cls.getModifiers())).append(" ")

.append(cls.getSimpleName()).append("\n");

sb.append("注解值: ").append(myClassAnnotation.value()).append("\n\n");

}

sb.append("Field注解:").append("\n");

Field[] fields = cls.getDeclaredFields();

for (Field field : fields) {

MyFieldAnnotation fieldInfo = field.getAnnotation(MyFieldAnnotation.class);

if (fieldInfo != null) {

sb.append(Modifier.toString(field.getModifiers())).append(" ")

.append(field.getType().getSimpleName()).append(" ")

.append(field.getName()).append("\n");

sb.append("注解值: ").append(fieldInfo.name()).append("\n\n");

}

}

sb.append("Method注解:").append("\n");

Method[] methods = cls.getDeclaredMethods();

for (Method method : methods) {

MyMethodAnnotation methodInfo = method.getAnnotation(MyMethodAnnotation.class);

if (methodInfo != null) {

sb.append(Modifier.toString(method.getModifiers())).append(" ")

.append(method.getReturnType().getSimpleName()).append(" ")

.append(method.getName()).append("\n");

sb.append("注解值: ").append("\n");

sb.append("name: ").append(methodInfo.name()).append("\n");

sb.append("age: ").append(methodInfo.age()).append("\n");

}

}

System.out.print(sb.toString());

}

}

测试结果如下:

Class注解:

public TestRuntimeAnnotation

注解值: test Class

Field注解:

public String fieldInfo

注解值: fieldName

Method注解:

public static String getMethodInfo

注解值:

name: zhangsan

age: 0

定义注解

该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。

定义注解

该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。

package org.xdemo.validation.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import org.xdemo.validation.RegexType;

/**

* 数据验证

* @author Goofy

*/

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD,ElementType.PARAMETER})

public @interface DV {

//是否可以为空

boolean nullable() default false;

//最大长度

int maxLength() default 0;

//最小长度

int minLength() default 0;

//提供几种常用的正则验证

RegexType regexType() default RegexType.NONE;

//自定义正则验证

String regexExpression() default "";

//参数或者字段描述,这样能够显示友好的异常信息

String description() default "";

}

注解的解析

package org.xdemo.validation.annotation.support;

import java.lang.reflect.Field;

import org.xdemo.validation.RegexType;

import org.xdemo.validation.annotation.DV;

import org.xdemo.validation.utils.RegexUtils;

import org.xdemo.validation.utils.StringUtils;

/**

* 注解解析

* @author Goofy

*/

public class ValidateService {

private static DV dv;

public ValidateService() {

super();

}

//解析的入口

public static void valid(Object object) throws Exception{

//获取object的类型

Class<? extends Object> clazz=object.getClass();

//获取该类型声明的成员

Field[] fields=clazz.getDeclaredFields();

//遍历属性

for(Field field:fields){

//对于private私有化的成员变量,通过setAccessible来修改器访问权限

field.setAccessible(true);

validate(field,object);

//重新设置会私有权限

field.setAccessible(false);

}

}

public static void validate(Field field,Object object) throws Exception{

String description;

Object value;

//获取对象的成员的注解信息

dv=field.getAnnotation(DV.class);

value=field.get(object);

if(dv==null)return;

description=dv.description().equals("")?field.getName():dv.description();

/*************注解解析工作开始******************/

if(!dv.nullable()){

if(value==null||StringUtils.isBlank(value.toString())){

throw new Exception(description+"不能为空");

}

}

if(value.toString().length()>dv.maxLength()&&dv.maxLength()!=0){

throw new Exception(description+"长度不能超过"+dv.maxLength());

}

if(value.toString().length()<dv.minLength()&&dv.minLength()!=0){

throw new Exception(description+"长度不能小于"+dv.minLength());

}

if(dv.regexType()!=RegexType.NONE){

switch (dv.regexType()) {

case NONE:

break;

case SPECIALCHAR:

if(RegexUtils.hasSpecialChar(value.toString())){

throw new Exception(description+"不能含有特殊字符");

}

break;

case CHINESE:

if(RegexUtils.isChinese2(value.toString())){

throw new Exception(description+"不能含有中文字符");

}

break;

case EMAIL:

if(!RegexUtils.isEmail(value.toString())){

throw new Exception(description+"地址格式不正确");

}

break;

case IP:

if(!RegexUtils.isIp(value.toString())){

throw new Exception(description+"地址格式不正确");

}

break;

case NUMBER:

if(!RegexUtils.isNumber(value.toString())){

throw new Exception(description+"不是数字");

}

break;

case PHONENUMBER:

if(!RegexUtils.isPhoneNumber(value.toString())){

throw new Exception(description+"不是数字");

}

break;

default:

break;

}

}

if(!dv.regexExpression().equals("")){

if(value.toString().matches(dv.regexExpression())){

throw new Exception(description+"格式不正确");

}

}

/*************注解解析工作结束******************/

}

}

用到的几个类

package org.xdemo.validation;

/**

* 常用的数据类型枚举

* @author Goofy

*

*/

public enum RegexType {

NONE,

SPECIALCHAR,

CHINESE,

EMAIL,

IP,

NUMBER,

PHONENUMBER;

}

其中正则验证类和字符串工具类请参考以下链接:

SuperUtil之RegexUtils

SuperUtil之StringUtils

使用方法

package org.xdemo.validation.test;

import org.xdemo.validation.RegexType;

import org.xdemo.validation.annotation.DV;

public class User {

@DV(description="用户名",minLength=6,maxLength=32,nullable=false)

private String userName;

private String password;

@DV(description="邮件地址",nullable=false,regexType=RegexType.EMAIL)

private String email;

public User(){}

public User(String userName, String password, String email) {

super();

this.userName = userName;

this.password = password;

this.email = email;

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

}

测试代码

import org.xdemo.validation.annotation.support.ValidateService;

/**

* @author Goofy

*/

public class Test {

public static void main(String[] args){

User user=new User("张三", "xdemo.org", "252878950@qq.com");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

user=new User("zhangsan","xdemo.org","xxx@");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

user=new User("zhangsan","xdemo.org","");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

}

}

Java自定义注解Annotation的使用的更多相关文章

  1. JAVA自定义注解 ------ Annotation

    日常开发工作中,合理的使用注解,可以简化代码编写以及使代码结构更加简单,下面记录下,JAVA自定义注解的开发过程. 定义注解声明类. 编写注解处理器(主要起作用部分). 使用注解. 相关知识点介绍, ...

  2. Java自定义注解Annotation详解

    注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去 ...

  3. java自定义注解类

    一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...

  4. java自定义注解实现前后台参数校验

    2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...

  5. Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

    不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...

  6. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  7. Java自定义注解的实现

    Java自定义注解的实现,总共三步(eg.@RandomlyThrowsException): 1.首先编写一个自定义注解@RandomlyThrowsException package com.gi ...

  8. Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)

    Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性) 前言:由于前段时间忙于写接口,在接口中需要做很多的参数校验,本着简洁.高效的原则,便写了这个小工具供自己使用(内容 ...

  9. Java自定义注解和运行时靠反射获取注解

    转载:http://blog.csdn.net/bao19901210/article/details/17201173/ java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编 ...

随机推荐

  1. java集合类笔试选择题整理含答案

    1.ArrayList list=new ArrayList(20);中的list扩充几次()A. 0B. 1C. 2D. 3答案:A分析:已经指定了长度, 所以不扩容 2.List.Set.Map哪 ...

  2. sqoop 数据导入hive

    一. sqoop: mysql->hive sqoop import -m 1 --hive-import --connect "jdbc:mysql://127.0.0.1:3306 ...

  3. Mysql学习笔记(003)-案例讲解基础查询

    案例讲解基础查询 #.下面的语句是否可以执行成功 SELECT last_name, first_name, salary AS sal FROM employees; #.下面的语句是否可以执行成功 ...

  4. spring+websocket的整合实例--可使用

    spring+websocket的整合实例----借鉴如下链接--此贴用于笔记 https://blog.csdn.net/qq_35515521/article/details/78610847

  5. mysql学习-explain

    表头包含有: id---select_type---table---type---possible_keys---key---key_len---ref---rows---Extra id:selec ...

  6. strlen、strcmp、strcat、strlen、memmove

    #include <cassert> #include <iostream> using namespace std; /* strlen 返回字符串不包含结束符\0的长度 * ...

  7. python学习笔记:使用freeze命令迁移模块

    使用freeze 给所有模块搬家 导出安装模块的文档pip freeze > my_freeze.txt 或者指定地址pip freeze > e:\my_freeze.txt 在另一个环 ...

  8. 04、python的基础-->列表跟元组

    一.列表list 1.列表的新增元素(三种方法) >>>第1种方法(append 增加到最后): li = ['Peter','Henrry','Wode','鸭子','xiaoxi ...

  9. Spring Cloud注册中心高可用搭建

    Spring Cloud的注册中心可以由Eureka.Consul.Zookeeper.ETCD等来实现,这里推荐使用Spring Cloud Eureka来实现注册中心,它基于Netfilix的Eu ...

  10. 开发效率优化之Git分布式版本控制系统(一)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680本篇文章将先从Git分布式版本控制系统来阐述开发效率优化 一,企业 ...