一篇文章彻底明白java中的重要概念——注解
1. 注解基本概念
注解,什么是注解?
打开百度搜索
好,看不懂
没关系
一步一步慢慢来
先不管注解,注释这个概念应该就很熟悉了,文档注释,单行注释,多行注释
注释是对一段程序,一个方法,一个类进行描述,是给我们程序员看的,都知道,注解是不会被编译的,会被忽略
注解,同样的道理,其实就是用来说明代码的,但是注解是 给计算机看的,是会被编译的
因此:
注解概念:jdk1.5之后出现,是对程序进行说明,并且会被编辑,给计算机看的
来看看toString 方法
Override 这个单词并不陌生java基础—重写、重载 ,没错 重写,子类重写父类的方法
如果我们 把这个方法改一下
可以看到注解 报错了 错误信息:
方法不是重写父类的方法
就像我们之前说的函数式接口 java8 (jdk 1.8) 新特性——Lambda
@FunctionalInterface 注解一样
所以注解的其中一个功能就出来了: 用来校验,编译检查
注解的格式:@+名称
2. JDK 中的内置注解
java提供了5个基本的注解:
这五个注解的介绍百度百科已经说的很清楚了,这边直接引用
限定父类重写方法:@Override
当子类重写父类方法时,子类可以加上这个注解,那这有什么什么用?这可以确保子类确实重写了父类的方法,避免出现低级错误
2. 标示已过时:@Deprecated
这个注解用于表示某个程序元素类,方法等已过时,当其他程序使用已过时的类,方法时编译器会给出警告(删除线,这个见了不少了吧)。
3.抑制编译器警告:@SuppressWarnings
被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告,例如修饰一个类,那他的字段,方法都是显示警告
4.“堆污染”警告与@SafeVarargs
想理解这个就要明白什么是堆污染,堆污染是什么?
其实很好理解,就是把不带泛型的对象赋给一个带泛型的对象,为什么不行?很简单,因为不带泛型的话,默认会给泛型设定为object,意思就是什么类型都可以往里面塞,那你一个不带泛型的怎么可能给一个带泛型塞呢。
例如运行如下代码:
List list = new ArrayList(); list.add(20);
List<String> ls = list; System.out.println(ls.get(0));
则会抛出堆污染异常Exception in thread “main” java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at Test.Test1.main(Test1.java:29)
注意:可变参数更容易引发堆污染异常,因为java不允许创建泛型数组,可变参数恰恰是数组。
抑制这个警告的方法有三个:
1.@SafeVarargs修饰引发该警告的方法或构造器
2.使用@suppressWarnings(“unchecked”)
3.编译时使用-Xlint:varargs
5.函数式接口与@Functionallnterface
什么是函数式?如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法)
接口体内只能声明常量字段和抽象方法,并且被隐式声明为public,static,final。
接口里面不能有私有的方法或变量。
这个注解有什么用?这个注解保证这个接口只有一个抽象方法,注意这个只能修饰接口
认识认识,有个印象
3.注解的功能
-
首先一个就是前边的 用来编译检查功能
-
其次,注解还有编写文档的功能
什么?编写文档,一脸懵逼,别急,看看就知道了
jdk 文档,应该程序员人手都有一份,没有的伙伴 公众号内回复【文档】 获取
其实这些文档就是通过注解生成的
事实胜于雄辩
我们先建一个类
桌面新建一个文件夹 api ,把这个类拷贝进去
cmd 然后进行javadoc 命令
可以看到生成了一堆文件,
双击打开index.html
是不是发现新大陆!!
-
再者,就是代码分析【这个就是最重要的了,Spring Aop 自定义注解都是这个用的这个功能,当然主要原理还是反射】 java进阶—反射
4. 注解本质
前边 说了,注解语法格式:@+名称
那么,是不是只要我们 @ +随便一个名字是不是就是注解呢?@OpLog
@UserLog
你当然可以这样定义,但并不是按照这种格式写了,编译器就能认,它背后是有进行一些操作的,也就是说让编译器认你写的这个是注解
照猫画虎,我们来看官方是怎么处理的
点开注解原码
格式:
元注解 public @interface 注解名称 { }