文章目录

  • 一. 什么是Annotation
  • 二. Annotation的作用
    • 2.1 编译器使用到的注解
    • 2.2 .class文件使用到的注解
    • 2.3 运行期读取的注解
  • 三. 定义Annotation
    • 3.1 元注解
      • 3.1.1 @Target
      • 3.1.2 @Retention
      • 3.1.3 @Documented
      • 3.1.4 @Inherited
    • 3.2 定义注解小结
  • 四. Annotation处理
  • 五. 总结

一. 什么是Annotation

我们在平时的开发过程中看到很多如@Override,@SuppressWarnings,@Test等样式的代码就是注解,注解是放到类、构造器、方法、属性、参数前的标记。

二. Annotation的作用

给某个类、方法…添加了一个注解,这个环节仅仅是做了一个标记,对代码本身并不会造成任何影响,需要后续环节的配合,需要其他方法对该注解赋予业务逻辑处理。就如同我们在微信上发了一个共享定位,此时并没有什么用,只有当后面其他人都进入了这个共享定位,大家之间的距离才能明确,才知道该怎么聚在一起。

注解分为三类:

2.1 编译器使用到的注解

如@Override,@SuppressWarnings都是编译器使用到的注解,作用是告诉编译器一些事情,而不会进入编译后的.class文件。

@Override:告诉编译器检查一下是否重写了父类的方法;

@SuppressWarnings:告诉编译器忽略该段代码产生的警告;

对于开发人员来说,都是直接使用,无需进行其他操作

2.2 .class文件使用到的注解

需要通过工具对.class字节码文件进行修改的一些注解,某些工具会在类加载的时候,动态修改用某注解标注的.class文件,从而实现一些特殊的功能,一次性处理完成后,并不会存在于内存中,都是非常底层的工具库、框架会使用,对于开发人员来说,一般不会涉及到。

2.3 运行期读取的注解

一直存在于JVM中,在运行期间可以读取的注解,也是最常用的注解,如Spring的@Controller,@Service,@Repository,@AutoWired,Mybatis的@Mapper,Junit的@Test等,这类注解很多都是工具框架自定义在运行期间发挥特殊作用的注解,一般开发人员也可以自定义这类注解。

三. 定义Annotation

我们使用@interface来定义一个注解

/*** 定义一个Table注解*/
public @interface Table {String value() default "";
}
/*** 定义一个Colum注解*/
public @interface Colum {String value() default "";String name() default "";String dictType() default "";
}

这样就简单地将一个注解定义好了

我们上面定义的注解主要用到了String类型,但实际上还可以是基本数据类型(不能为包装类)、枚举类型。

注解也有一个约定俗成的东西,最常用的参数应该命名为value,同时一般情况下我们都会通过default参数设置一个默认值。

但这样是不是就满足于我们的使用了呢,我想把@Table注解仅用于类上,@Colum注解仅用于属性上,怎么办?而且开始提到的三类注解,一般开发人员用的都是运行期的注解,那我们定义的是吗?

要回答这些问题,就需要引入一个概念“元注解”。

3.1 元注解

可以修饰注解的注解即为元注解,Java已经定义了一些元注解,我们可以直接使用。

3.1.1 @Target

顾名思义指定注解使用的目标对象,参数为ElementType[]

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();
}

而下面是ElementType枚举中定义的属性,不设置Target的时候,除了TYPE_PARAMETER,TYPE_USE,其他地方都相当于配置上了。

public enum ElementType {/** 通过ElementType.TYPE可以修饰类、接口、枚举 */TYPE,/** 通过ElementType.FIELD可以修饰类属性 */FIELD,/** 通过ElementType.METHOD可以修饰方法 */METHOD,/** 通过ElementType.PARAMETER可以修饰参数(如构造器或者方法中的) */PARAMETER,/** 通过ElementType.CONSTRUCTOR可以修改构造器 */CONSTRUCTOR,/** 通过ElementType.LOCAL_VARIABLE可以修饰方法内部的局部变量 */LOCAL_VARIABLE,/** 通过ElementType.ANNOTATION_TYPE可以修饰注解 */ANNOTATION_TYPE,/** 通过ElementType.PACKAGE可以修饰包 */PACKAGE,/*** 可以用在Type的声明式前** @since 1.8*/TYPE_PARAMETER,/*** 可以用在所有使用Type的地方(如泛型、类型转换等)** @since 1.8*/TYPE_USE
}

我们主要说一下ElementType.PACKAGE和1.8添加的ElementType.TYPE_PARAMETER和ElementType.TYPE_USE

ElementType.PACKAGE

@Target(ElementType.PACKAGE)
public @interface Table {String value() default "";
}

含义是用来修饰包,但我们用来修饰包的时候却提示错误

我们按照提示创建package-info.java文件,这里需要注意一下,通过IDE 进行new --> Java Class是创建不了的,需要通过new File文件创建

@Table
package annotation;
class PackageInfo {public void hello() {System.out.println("hello");}
}

ElementType.TYPE_PARAMETER和ElementType.TYPE_USE

这两个一起说,因为它们有相似之处。都是Java1.8后添加的

@Target(ElementType.TYPE_USE)
public @interface NoneEmpty {String value() default "";
}
@Target(ElementType.TYPE_PARAMETER)
public @interface NoneBlank {String value() default "";
}

很明显使用ElementType.TYPE_PARMETER修饰的注解@NoneBlank无法在泛型使用的时候编译通过,仅能用于类的泛型声明,而通过ElementType.TYPE_USE修饰的注解@NoneEmpty可以。

3.1.2 @Retention

可以用于定义注解的生命周期,参数为枚举RetentionPolicy,包括了SOURCE,CLASS,RUNTIME

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {/*** Returns the retention policy.* @return the retention policy*/RetentionPolicy value();
}
public enum RetentionPolicy {/*** 仅存在于源代码中,编译阶段会被丢弃,不会包含于class字节码文件中.*/SOURCE,/*** 【默认策略】,在class字节码文件中存在,在类加载的时被丢弃,运行时无法获取到*/CLASS,/*** 始终不会丢弃,可以使用反射获得该注解的信息。自定义的注解最常用的使用方式。*/RUNTIME
}

3.1.3 @Documented

表示是否将此注解的相关信息添加到javadoc文档中

3.1.4 @Inherited

定义该注解和子类的关系,使用此注解声明出来的自定义注解,在使用在类上面时,子类会自动继承此注解,否则,子类不会继承此注解。注意,使用@Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Person {String value() default "man";
}
@Person
public class Parent {}
//子类也拥有@Person注解
class Son extends Parent {}

3.2 定义注解小结

用@interface定义注解

可以添加多个参数,核心参数按约定用value,为每个参数可以设置默认值,参数类型包括基本类型、String和枚举

可以使用元注解来修饰注解,元注解包括多个,必须设置@Target@Retention@Retention一般设置为RUNTIME

四. Annotation处理

我们前面已经提到光配置了注解,其实没有作用,需要通过相应的代码来实现该注解想要表达的逻辑。

注解定义后也是一种class,所有的注解都继承自java.lang.annotation.Annotation,因此,读取注解,需要使用反射API。

//定义的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Colum {String value() default "";//用于表示某个属性代表的中文含义String name() default "";
}

用注解@Colum来修饰某个类的属性

public class Person {@Colum(name = "姓名")private String name;@Colum(name = "性别")private String gender;@Colum(name = "年龄")private int age;@Colum(name = "住址")private String address;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}

通过反射读取这个类的所有字段的中文含义,并保存到list中,然后打印出来

public static void main(String[] args) throws ClassNotFoundException {List<String> columNames = new ArrayList<>();Class clazz = Class.forName("annotation.Person");//获取Person类所有属性Field[] fields = clazz.getDeclaredFields();for (Field field : fields){//获取该属性的Colum注解Colum colum = field.getAnnotation(Colum.class);//或者可以先判断有无该注解field.isAnnotationPresent(Colum.class);//将该属性通过注解配置好的中文含义取出来放到集合中columNames.add(colum.name());}//打印集合columNames.forEach((columName) -> System.out.println(columName));
}

结果如下:

姓名
性别
年龄
住址

比如我们有一些常见的应用场景,需要把网站上的列表导出成excel表格,我们通过注解的方式把列名配置好,再通过反射读取实体需要导出(是否需要导出,也可通过注解配置)的每个字段的值,从而实现excel导出的组件。

五. 总结

本文只是抛砖引玉地讲解了注解的基本概念,注解的作用,几种元注解的功用以及使用方法,并通过一个简单的例子讲解了一下注解的处理,并不全面,文中通过Field讲解了注解的基本Api,但注解还可以修饰类、构造器、方法等,也有相对应的注解处理方法,大家可自行查一下API手册相关内容,大同小异,有不对之处,请批评指正,望共同进步,谢谢!

一起来学Java注解(Annotation)相关推荐

  1. Java注解(Annotation)详解

    转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...

  2. Java注解Annotation 完成验证

    Java注解Annotation用起来很方便,也越来越流行,由于其简单.简练且易于使用等特点,很多开发工具都提供了注解功能,不好的地方就是代码入侵比较严重,所以使用的时候要有一定的选择性. 这篇文章将 ...

  3. java注释和注解_深入理解JAVA注解(Annotation)以及自定义注解

    Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制.Java 语言中的类.方法.变量.参数和包等都可以被标注.注解可以看作是一种特殊的标记,在程序在编译或 ...

  4. java 注解: Annotation

    java 注解: Annotation 普通注解 自定义注解 元注解 注解: 位于源码中,用来修饰程序的元素,但不会对被修饰的对象有直接的影响. 可增加程序的动态性. 普通注解 普通注解:为java代 ...

  5. Java注解annotation invalid type of annotation member

    文章目录 Java注解annotation : invalid type of annotation member 1.什么是invalid type of annotation member 2.哪 ...

  6. Java 注解(Annotation)使用方法归纳

    Java注解Annotation使用方法归纳 简介 注解是从JDK5开始支持,是Java对元数据的一种特殊支持.与注释有一定区别,可以理解为代码上的特殊标记,通过这些标记我们可以在编译,类加载,运行等 ...

  7. 深入理解Java注解Annotation之注解处理器

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...

  8. 深入理解Java注解Annotation及自定义注解

    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...

  9. Java注解Annotation详解

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

最新文章

  1. 从城市大脑到世界数字大脑 构建人类协同发展的超级智能平台
  2. ubuntu 12.04.1升级至ubuntu 12.10出现gcc-4.7依赖库错误的解决办法
  3. C语言 —— 预定义符号__FILE____LINE___func__(编写调试函数printf , debug)
  4. Python入门100题 | 第025题
  5. win7冒险岛java,win7玩冒险岛不兼容怎么办?解决win7玩冒险岛不兼容的方法
  6. 微众WeCross 跨链平台(12)合约总结
  7. python自动化测试面试题代码_Python自动化测试常见面试题(四)
  8. 读书笔记_CLR.via.c#第十六章_数组
  9. 阿里云上git clone公司内网仓库遇到的错误消息 - cannot resolve host
  10. BOM(Browser Object Model)
  11. Tomcat启动时报org.springframework.web.context.ContextLoaderListener错误解决方案
  12. AMD,CMD,UMD,CommonJS
  13. python标准正态分布表(scipy.stats)
  14. 中兴B860AV2.1-T刷机教程加固件
  15. js检查ie低版本浏览器,并跳转更新页面
  16. Establishing SSL
  17. 使用Python横向合并excel文件
  18. 在Matlab中构建最大带权生成树
  19. 内网异地备份_用批处理实现局域网内的异地备份
  20. Silvaco学习笔记(一)毕设相关

热门文章

  1. Lipschitz函数
  2. C++跨平台开源库 之一
  3. kafka.errors.KafkaTimeoutError: KafkaTimeoutError
  4. 有没有通话质量比较好的蓝牙耳机?高清通话的蓝牙耳机推荐
  5. 2021-04-29 Ubuntu重启 关机命令
  6. Android自定义控件图片+文字布局
  7. 基于SpringBoot的体育场馆运营管理系统的设计与实现
  8. 华为鸿蒙如何安装,华为鸿蒙OS发布会解析,这些技术干货你应该知道
  9. cadence SPB17.4 - allegro - WARNING: Unsupported curve-fit, spline, or 3D POLYLINE
  10. 【Word】Word数字编号到10以后与文字之间间隙过大的解决办法