Java注解是一个很重要的知识点,掌握好Java注解有利于学习Java开发框架底层实现。@mikechen

Java注解定义

Java注解又称Java标注,是在 JDK5 时引入的新特性,注解(也被称为元数据)。

Java注解它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。

Java注解应用

1.生成文档这是最常见的,也是java 最早提供的注解;

2.在编译时进行格式检查,如@Override放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出;

3.跟踪代码依赖性,实现替代配置文件功能,比较常见的是spring 2.5 开始的基于注解配置,作用就是减少配置;

4.在反射的 Class, Method, Field 等函数中,有许多于 Annotation 相关的接口,可以在反射中解析并使用 Annotation。

Java注解分类

1、Java自带的标准注解

包括@Override、@Deprecated、@SuppressWarnings等,使用这些注解后编译器就会进行检查。

2、元注解

元注解是用于定义注解的注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等。
元注解也是Java自带的标准注解,只不过用于修饰注解,比较特殊。

3、自定义注解

用户可以根据自己的需求定义注解。

Java标准注解

JDK 中内置了以下注解:

1.@Override

如果试图使用 @Override 标记一个实际上并没有覆写父类的方法时,java 编译器会告警。

  1. class Parent {
  2. public void test() {
  3. }
  4. }
  5.  
  6. class Child extends Parent {
  7. /**
  8. * 放开下面的注释,编译时会告警
  9. */
  10. /*
  11. @Override
  12. public void test() {
  13. }
  14. */
  15. }

2.Deprecated

  1. @Deprecated 用于标明被修饰的类或类成员、类方法已经废弃、过时,不建议使用。
  2. @Deprecated
  3. class TestClass {
  4. // do something
  5. }

3.@SuppressWarnings

@SuppressWarnings 用于关闭对类、方法、成员编译时产生的特定警告。

1)抑制单类型的警告

  1. @SuppressWarnings("unchecked")
  2. public void addItems(String item){
  3. @SuppressWarnings("rawtypes")
  4. List items = new ArrayList();
  5. items.add(item);
  6. }

2)抑制多类型的警告

  1. @SuppressWarnings(value={"unchecked", "rawtypes"})
  2. public void addItems(String item){
  3. List items = new ArrayList();
  4. items.add(item);
  5. }

3)抑制所有类型的警告

  1. @SuppressWarnings("all")
  2. public void addItems(String item){
  3. List items = new ArrayList();
  4. items.add(item);
  5. }

@SuppressWarnings 注解的常见参数值的简单说明:

4.@FunctionalInterface

@FunctionalInterface 用于指示被修饰的接口是函数式接口,在 JDK8 引入。

  1. @FunctionalInterfacepublic interface UserService {
  2.  
  3. void getUser(Long userId);
  4.  
  5. // 默认方法,可以用多个默认方法
  6. public default void setUser() {
  7. }
  8.  
  9. // 静态方法
  10. public static void saveUser() {
  11. }
  12.  
  13. // 覆盖Object中的equals方法
  14. public boolean equals(Object obj);}

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

Java元注解

元注解是java API提供的,是用于修饰注解的注解,通常用在注解的定义上:

1.@Retention

@ Retention用来定义该注解在哪一个级别可用,在源代码中(SOURCE)、类文件中(CLASS)或者运行时(RUNTIME)。

@Retention 源码:

  1. @Documented@Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.ANNOTATION_TYPE)
  3. public @interface Retention {
  4. RetentionPolicy value();
  5. }
  6. public enum RetentionPolicy {
  7. //此注解类型的信息只会记录在源文件中,编译时将被编译器丢弃,也就是说
  8. //不会保存在编译好的类信息中
  9. SOURCE,
  10. //编译器将注解记录在类文件中,但不会加载到JVM中。如果一个注解声明没指定范围,则系统
  11. //默认值就是Class
  12. CLASS,
  13. //注解信息会保留在源文件、类文件中,在执行的时也加载到Java的JVM中,因此可以反射性的读取。
  14. RUNTIME
  15. }

RetentionPolicy 是一个枚举类型,它定义了被 @Retention 修饰的注解所支持的保留级别:

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.SOURCE) //注解信息只能在源文件中出现
  3. public @interface Override {
  4. }
  5. @Documented@Retention(RetentionPolicy.RUNTIME) //注解信息在执行时出现@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
  6. public @interface Deprecated {
  7. }
  8. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
  9. @Retention(RetentionPolicy.SOURCE) //注解信息在源文件中出现
  10. public @interface SuppressWarnings {
  11. String[] value();
  12. }

2.@Documented

@Documented:生成文档信息的时候保留注解,对类作辅助说明

@Documented 示例

  1. @Target(ElementType.FIELD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Column {
  5. public String name() default "fieldName";
  6. public String setFuncName() default "setField";
  7. public String getFuncName() default "getField";
  8. public boolean defaultDBValue() default false;
  9. }

3.@Target

@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

@Target源码:

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.ANNOTATION_TYPE)
  4. public @interface Target {
  5. ElementType[] value();
  6. }

ElementType 是一个枚举类型,它定义了被 @Target 修饰的注解可以应用的范围:

4.@Inherited

@Inherited:说明子类可以继承父类中的该注解

表示自动继承注解类型。 如果注解类型声明中存在 @Inherited 元注解,则注解所修饰类的所有子类都将会继承此注解。

  1. @Inherited
  2. public @interface Greeting {
  3. public enum FontColor{ BULE,RED,GREEN};
  4. String name();
  5. FontColor fontColor() default FontColor.GREEN;
  6. }

5.@Repeatable

@Repeatable 表示注解可以重复使用。

当我们需要重复使用某个注解时,希望利用相同的注解来表现所有的形式时,我们可以借助@Repeatable注解。
以 Spring @Scheduled 为例:

  1. @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Schedules {
  5. Scheduled[] value();
  6. }
  7.  
  8. @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. @Repeatable(Schedules.class)
  12. public @interface Scheduled {
  13. // ...
  14. }

自定义注解

当我们理解了内置注解, 元注解和获取注解的反射接口后,我们便可以开始自定义注解了。

创建自定义注解和创建一个接口相似,但是注解的interface关键字需要以@符号开头,我们可以为注解声明方法。

自定义注解格式:

  1. // 元注解
  2. public @interface 注解名称{
  3. // 属性列表
  4. }

我们先来看看注解的例子:

1.创建自定义注解

  1. /**
  2. * 自定义注解例子
  3. *
  4. * @author mikechen
  5. */
  6.  
  7. @Documented
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target(ElementType.METHOD)
  10. @Inherited
  11. public @interface HelloAnnotation {
  12. String value();
  13. }

2.使用自定义注解

  1. /**
  2. * 使用自定义注解
  3. *
  4. * @author mikechen
  5. */
  6. public class HelloAnnotationClient {
  7. @HelloAnnotation(value="Simple custom Annotation example")
  8. public void sayHello(){
  9. System.out.println("Inside sayHello method..");
  10. }
  11. }

3.测试自定义注解

  1. /**
  2. * 自定义注解测试
  3. *
  4. * @author mikechen
  5. */
  6. public class HelloAnnotationTest {
  7. public static void main(String[] args) throws Exception {
  8. HelloAnnotationClient helloAnnotationClient=new HelloAnnotationClient();
  9. Method method=helloAnnotationClient.getClass().getMethod("sayHello");
  10. if(method.isAnnotationPresent(HelloAnnotation.class)){
  11. HelloAnnotation helloAnnotation=method.getAnnotation(HelloAnnotation.class);
  12. //Get value of custom annotation
  13. System.out.println("Value : "+helloAnnotation.value());
  14. //Invoke sayHello method
  15. method.invoke(helloAnnotationClient); }
  16. }
  17. }

以上

作者简介

陈睿|mikechen,10年+大厂架构经验,《BAT架构技术500期》系列文章作者,分享十余年BAT架构经验以及面试心得!

阅读mikechen的互联网架构更多技术文章合集

Java并发|JVM|MySQL|Spring|Redis|分布式|高并发|架构师

Java注解最全详解(超级详细)的更多相关文章

  1. SPRINGBOOT注解最全详解(

    #     SPRINGBOOT注解最全详解(整合超详细版本)          使用注解的优势:               1.采用纯java代码,不在需要配置繁杂的xml文件           ...

  2. Java注解处理器使用详解

    在这篇文章中,我将阐述怎样写一个注解处理器(Annotation Processor).在这篇教程中,首先,我将向您解释什么是注解器,你可以利用这个强大的工具做什么以及不能做什么:然后,我将一步一步实 ...

  3. Spring AOP全面详解(超级详细)

    如果说 IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心@mikechen AOP的定义 AOP (Aspect Orient Programming ...

  4. (转)java之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  5. java的集合框架最全详解

    java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...

  6. 超全详解Java开发环境搭建

    摘自:https://www.cnblogs.com/wangjiming/p/11278577.html 超全详解Java开发环境搭建   在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必 ...

  7. Java编程配置思路详解

    Java编程配置思路详解 SpringBoot虽然提供了很多优秀的starter帮助我们快速开发,可实际生产环境的特殊性,我们依然需要对默认整合配置做自定义操作,提高程序的可控性,虽然你配的不一定比官 ...

  8. Java 8 Lambda 表达式详解

    一.Java 8 Lambda 表达式了解 参考:Java 8 Lambda 表达式 | 菜鸟教程 1.1 介绍: Lambda 表达式,也可称为闭包,是推动 Java 8 发布的最重要新特性. La ...

  9. MyBatis 一级缓存、二级缓存全详解(一)

    目录 MyBatis 一级缓存.二级缓存全详解(一) 什么是缓存 什么是MyBatis中的缓存 MyBatis 中的一级缓存 初探一级缓存 探究一级缓存是如何失效的 一级缓存原理探究 还有其他要补充的 ...

随机推荐

  1. PostgreSQL 的窗口函数 OVER, WINDOW, PARTITION BY, RANGE

    最近在数据处理中用到了窗函数, 把使用方法记录一下, 暂时只有分组排序和滑动时间窗口的例子, 以后再逐步添加 场景 在SQL查询时, 会遇到有两类需要分组统计的场景, 在之前的SQL语法中是不方便实现 ...

  2. boost::bind 不能处理函数重载 (error: no matching function for call to 'bind')

    前言 最近任务多.工期紧,没有时间更新博客,就水一期吧.虽然是水,也不能太失水准,刚好最近工作中遇到一个 boost::bind 的问题,花费了半天时间来定位解决,就说说它吧. 问题背景 项目中使用了 ...

  3. nginx 代理请求导出功能bug解决方法

    问题描述: nginx代理的ip直接访问可以直接下载文件,但是通过nginx访问就报502,nginx错误日志:upstream sent invalid chunked response while ...

  4. 【SpringSecurity系列1】基于SpringSecurity实现前后端分离无状态Rest API的权限控制

    源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...

  5. 如何利用 RPA 实现自动化获客?

    大家好,我是二哥.前高级技术专家 & 增长黑客,现一枚爱折腾的小小创业者,专注于 RPA & SaaS 软件这块.这次给大家带来如何利用 RPA 实现自动化获客 一.RPA 是什么?难 ...

  6. tableSizeFor

    HashMap tableSizeFor() /** Returns a power of two size for the given target capacity. 1.(不考虑大于最大容量的情 ...

  7. Integer.MAX_VALUE 和 Integer.MIN_VALUE

    在源码中可以看出其对应的值 Integer.MAX_VALUE是2^31 -1 = 2147483647 Integer.MIN_VALUE是-2^31 =  -2147483648

  8. 内存分析器 (MAT)

    内存分析器 (MAT) 1. 内存分析器 (MAT) 1.1   MAT介绍 MAT是Memory Analyzer tool的缩写.指分析工具. 1.2   MAT作用 Eclipse Memory ...

  9. ​​​​​​​ARCGIS API for Python进行城市区域提取

    ​ArcGIS API for Python主要用于Web端的扩展和开发,提供简单易用.功能强大的Python库,以及大数据分析能力,可轻松实现实时数据.栅格数据.空间数据等多源数据的接入和GIS分析 ...

  10. Image-Text Matching

    重要性和意义: Image-text matching has received a large amount of interest since it associates different mo ...