[转帖]java注解核心知识总结
1. 前言
前几年我们的项目还在structs 2 上跑,有一次问一个同事是否知道 Spring Boot,同事说那不是用注解来开发的吗。虽然这个答案并不完全对,但是从客观上Spring Boot对刚刚接触它的人来说最醒目的就是注解了。那么今天我们来了解一下Java语言的核心功能——注解。
2.注解是什么
public @interface Anno { }
以上就是一个最简单的注解声明。它可以注释到类、接口、方法以及变量上。通过向方法,接口,类或字段添加注释,为其绑定的源代码分配额外的元数据。
3.注解的用途
通过注解我们可以通知编译器有关警告和错误的信息在编译时操作源代码在运行时修改或检查行为。jdk提供内置5个基本注解来处理代码检查。
- @Override 来标记该方法重写或替换继承的方法的行为。如果你重写了父类方法不带该注解会触发一些警告。
- @SuppressWarnings 表示我们要忽略部分代码中的某些警告。如忽略潜在的类型不安全转换警告unchecked。
- @Deprecated 用来表示类、方法已经过时,不推荐使用。如果你强行使用编译器会在编译时进行警告。
- @Safevarargs 抑制“堆污染”警告。“堆污染”指的是将一个不带泛型的对象赋给带泛型的变量时引发的的类型问题。如果你不想看到该警告就可以使用该注解来抑制。
- @FunctionalInterface java 8 新增注解,只能作用于接口上来标识该接口是函数式接口。java中函数式接口表示该接口只能有一个抽象方法。如果一个接口被此注解修饰,如果添加第二个抽象方法将无法通过编译。
注解可以将一些元数据传递给你编写的逻辑。比如Spring Mvc 中的一个常用注解@RequestMapping,我们可以通过value参数来传递一个path路径,Spring Mvc通过对请求的路径的匹配来作出是否路由到该path上。 目前大量的的框架都依赖注解,比如Spring、hibernate、dubbo等等。
4.元注解
元注解是可以应用于其他注解的注解。来增强或者配置目标注解的机制。jdk目前提供了5个元注解。如果你需要开发自定义注解,请务必熟悉它们:
- @Retention 只能用于修饰注解,来指定被修饰注解可以保留多长时间。规定了三种策略:
- RetentionPolicy.SOURCE 这种策略下被修饰的注解只能存在于源代码中,编译后被丢弃,通过反射无法获取到被修饰的注解。
- RetentionPolicy.CLASS 这种策略下被修饰的注解会被编译进字节码文件中。但是JVM无法获取到被修饰的注解。这是一个默认值,当你声明的注解没有添加任何保留策略时,会默认指定该策略。
- RetentionPolicy.RUNTIME 这种策略下被修饰的注解不但可以编译进字节码文件。而且JVM也可以获取被该注解修饰的注解。而且程序编码也可以通过反射来获取被该注解修饰的注解的一些元信息。
- @Target 用于指定被修饰注解的修饰目标类型。如果一个注解明确了可修饰的目标类型,则只能修饰指定的类型。由枚举ElementType来规定。
- TYPE 只能修饰 类、接口、枚举。
- FIELD 只能修饰成员变量,包含枚举内的常量。
- METHOD 只能修饰方法。
- PARAMETER 只能修饰参数。
- CONSTRUCTOR 只能修饰构造器。
- LOCAL_VARIABLE 只能修饰局部变量。
- ANNOTATION_TYPE 只能修饰注解。
- PACKAGE 只能修饰包定义。也就是package-info.java中
- TYPE_PARAMETER java 8 新增 表示该注解能写在类型参数的声明语句中。 类型参数声明如: 、
- TYPE_USE java 8 新增 注解可以再任何用到类型的地方使用。
- @Documented 被该注解修饰的注解可以被javadoc工具提取为文档。
- @Inherited 被该注解修饰的注解有继承性。这里要注意一些要点首先这种继承性体现的类之间而不是接口之间,而且注解必须是对JVM可见。也就是@Retention为RetentionPolicy.RUNTIME 才起作用。
- @Repeatable java 8 新增。在此之前在同一个元素上同一个注解只能出现一次。@Repeatable可以让一个注解多次出现在一个元素上。
5.自定义注解
自定义注解跟自定义接口类似,但是还有一些区别,实际开发你需要对自定义注解进行元注解注释。注解中的成员变量以无参抽象方法来声明,成员变量并不是所有类型都支持,目前只支持以下类型:
- 所有基本类型(int,float,boolean,byte,double,char,long,short)
- String
- Class (如:Class<?> 或 Class)
- enum java枚举
- Annotation
- 下面我们就来自定义一个注解:
/** * 声明一个可以标记在类、接口、枚举、方法上的注解。 * 并且JVM Runtime 可见、可生成文档 * * @author Dax * @since 17 :27 2019/9/4 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Anno { /** * 若方法名为value且注解声明只需要声明value属性时, * value可以省略, @Anno("anno") 等同于 @Anno(value="anno") * * @return the string */ String value(); /** * 一个具有默认值的 String 类型属性。 * name若不显式声明,则默认值为"" 。 * 声明默认值通过 default + 默认值 来声明 * * @return the string */ String name() default ""; /** * 一个Class 类型属性,没有默认值。其他支持类型不再举例 * * @return the class */ Class<?> clazz(); }
如何获取注解中的元数据
所有的注解都是java.lang.annotation.Annotation 的子类。只有RetentionPolicy为RUNTIME的 注解才能通过反射获取。在反射包中提供了AnnotatedElement 接口来对元素上的可捕捉到的注解进行处理。该接口是Class、Method、Constructor等程序元素对象的父接口。也就是说只要能获取程序元素对象就能对其存在的注解进行处理。主要方法有:
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断是否存在 annotationClass类型的注解。
- T getAnnotation(Class annotationClass) 如果在当前元素上存在参数所指定类型(annotationClass)的注解,则返回对应的注解,否则将返回null。
- Annotation[] getAnnotations() 返回在这个元素上的所有注解。如果该元素没有注解,则返回值是长度为0的数组。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。
- T[] getAnnotationsByType(Class annotationClass) 返回与该元素相关联的注解。如果没有与此元素相关联的注解,则返回值是长度为0的数组。这个方法与getAnnotation(Class)的区别在于,该方法检测其参数是否为可重复的注解类型(JLS 9.6),如果是,则尝试通过“looking through”容器注解来查找该类型的一个或多个注解。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。参考@Repeatable。
- T getDeclaredAnnotation(Class annotationClass) 如果参数中所指定类型的注解是直接存在于当前元素上的,则返回对应的注解,否则将返回null。这个方法忽略了继承的注解。(如果没有直接在此元素上显示注释,则返回null。)
- T[] getDeclaredAnnotationsByType(Class annotationClass) 可获取重复注解但是忽略掉继承注解。
- Annotation[] getDeclaredAnnotations() 跟上面的注解区别在于不能获取重复注解。
基本上对这个接口的方法进行学习后就可以知道如何获取注解的元数据了。下面我们写一个例子,还是上面的Anno注解为例:
/**
* 被注解标记的类
**/
@Anno("hello")
public class Foo {}
/**
* 通过获取Foo 的Class 类,
* 然后就可以根据上面已经介绍的方法来获取value的值了
* @author dax
* @since 2019/9/4 22:17
*/
public class Main {
public static void main(String[] args) {
Anno annotation = Foo.class.getAnnotation(Anno.class);
String value = annotation.value();
System.out.println("value = " + value);
}
总结
今天我们系统地对注解进行了归纳,相信你已经对注解有了系统性的认识。
来源:掘金 链接:https://juejin.im/post/5db79e6c6fb9a0206f47bfd2
私信回复“资料”获取面试宝典《Java核心知识点整理.pdf》“,覆盖了JVM、锁、高并发、反射、Spring原理
[转帖]java注解核心知识总结的更多相关文章
- [转帖]java注解与注释注解区别
https://baijiahao.baidu.com/s?id=1615942718081024481&wfr=spider&for=pc 还需要仔细看一下书的 书里面都有. jav ...
- 深入理解 Java 多线程核心知识
多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关 ...
- 2018跳槽面试必备之深入理解 Java 多线程核心知识
导语:多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线 ...
- 深入理解 Java 多线程核心知识:跳槽面试必备
多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关 ...
- Java多线程核心知识(跳槽面试必备)
多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关 ...
- Java多线程核心知识
多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关 ...
- JAVA注解基础知识
定义-摘自JAVA编程思想 注解(元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们在稍后某个时刻能非常方便的使用这些数据. 背景: 注解是JAVA5的一种新特性,是为应对C#等之类对JAV ...
- Java注解Annotation与自定义注解详解
Java注解简介 开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解. 下面列举开发中常见的注解 @Override:用于标识 ...
- Java核心知识体系2:注解机制详解
1 Java注解基础 注解是JDK1.5版本开始引入的一个特性,用于对程序代码的说明,可以对包.类.接口.字段.方法参数.局部变量等进行注解. 它主要的作用有以下四方面: 生成javadoc文档,通过 ...
随机推荐
- 2019-08-26 linux
1.question:什么是linux? answer:Linux由林纳斯·托瓦兹开发的一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户.多任务.支持多线程和多CPU ...
- CRM product model的用法
User scenario An example from sap help For a car, the interior, the engine capacity, and the exterio ...
- 【Cookie】java.lang.IllegalArgumentException An invalid character [32] was present in the Cookie value
创建时间:6.30 java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie va ...
- C++ 梳理:跑通简单程序
C++ 结合了三个编程流派: 过程式编程:C 特性,结构化语言,强调过程 面向对象编程:C++ 对于 C 语言的补充,一切皆对象,强调数据 泛型编程(generic programming):由 C+ ...
- 浅谈僵尸网络利器:Fast-flux技术
浅谈僵尸网络利器:Fast-flux技术 一.背景 在早期的僵尸网络中,控制者通常会把C&C服务器的域名或者IP地址硬编码到恶意程序中,僵尸主机通过这些信息定时访问C&C主机获取命 ...
- nginx访问jupyter
现在jupyter已通过k8s安装完成,并通过nodeport暴露出来. 如果不能直接访问这个nodeport(像我在的公司)或是希望能组织好jupyter实例, 那应该如何调通呢? 这里包括两个技术 ...
- CEF 拦截打开超链接事件
使用 CEF 加载指定页面后,如果你希望控制页面在打开超链接时根据自己预定义的一些行为来操作,比如在自己的 UI 框架中新建一个 Tab 页又或者阻止打开新的页面等.我们就需要通过 CEF 提供的两个 ...
- Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。
Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得 ...
- 知识点5 C++保存txt文件
简单示例 #include <windows.h> #include <fstream> #include <iostream> #include <stri ...
- 掌握Visual Studio断点
我知道你现在在想什么.断点?真的吗?关于断点有什么需要掌握的?你按F9然后停在代码行.如果你是这么想的,这篇文章是给你的:继续读 Visual Studio提供了一组相当丰富的断点类型和操作,可以使您 ...