文章参考:https://www.cnblogs.com/xuningchuanblogs/p/7763225.html
https://www.cnblogs.com/xdp-gacl/p/3622275.html
学习网站:how2java.cn
1.注解是什么
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,没有加,则等于没有任何标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
2.为什么要用注解
使用Annotation之前(甚至在使用之后),XML被广泛的应用于描述元数据。不知何时开始一些应用开发人员和架构师发现XML的维护越来越糟糕了。他们希望使用一些和代码紧耦合的东西,而不是像XML那样和代码是松耦合的(在某些情况下甚至是完全分离的)代码描述。
假如你想为应用设置很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来,开发人员也必须认识到这点。
另一个很重要的因素是Annotation定义了一种标准的描述元数据的方式。在这之前,开发人员通常使用他们自己的方式定义元数据。例如,使用标记interfaces,注释,transient关键字等等。每个程序员按照自己的方式定义元数据,而不像Annotation这种标准的方式。
目前,许多框架将XML和Annotation两种方式结合使用,平衡两者之间的利弊。
简单来说:本来可能需要很多配置文件,需要很多逻辑才能实现的内容,就可以使用一个或者多个注解来替代,这样就使得编程更加简洁,代码更加清晰。
3.怎么使用注解
一、注解的分类
(1)按照运行机制划分:
1)源码注解: 只在源码中存在,编译成.class文件就不存在了
2)编译时注解: 在源码和.class中都存在,像@Override @Deprecated @SuppressWarnning等都属于编译时注解
3)运行时注解: 在运行阶段还起作用,甚至会影响运行逻辑的注解。像@Autowired自动注入的这样一种注解就属于运行时注解,它会在程序运行的时候把你的成员变量自动注入进来。
(2)按照来源划分:1)来自JDK的内置注解 2)来自第三方的注解 3)自定义注解
(3)元注解:元注解就是给注解进行注解,可以理解为注解的注解就是元注解(都不认识注解俩字了)
二、详细举例:
(1)基本内置注解
1)@Override:
@Override 用在方法上,表示这个方法重写了父类的方法,如toString()。如果父类没有这个方法,那么就无法编译通过,如例所示,在fromString()方法上加上@Override 注解,就会失败,因为Hero类的父类Object,并没有fromString方法
public class Person { String name; @Override public String toString(){ return name; }
@Override public String fromString(){ return name; }
}
2) @Deprecated:
@Deprecated 表示这个方法已经过期,不建议开发者使用。(暗示在将来某个不确定的版本,就有可能会取消掉)
public class Person { String name; @Deprecated public void doBad(){ System.out.println(""); }}
之后在使用doBad()方法时就会有破折号提示:这个方法已过时
3)@SuppressWarnings:
@SuppressWarnings Suppress英文的意思是抑制的意思,这个注解的用处是忽略警告信息。比如大家使用集合的时候,为了不去定义泛型,就会使用这个注解:
@SuppressWarnings({"rawtype","unused"}) public static void main(String[] args){ List list = new ArrayList(); }
或者使用上面@Deprecated注解过的方法时,为了消除过时提示,也会使用抑制注解
@SuppressWarnings("deprecation") public static void main(String[] args){ Person p = new Person(); p.doBad(); }
@SuppressWarnings的常见值如下:
1.deprecation:使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告);
2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告 3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告; 4.path:在类路径、源文件路径等中有不存在的路径时的警告; 5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告; 6.finally:任何 finally 子句不能正常完成时的警告; 7.rawtypes 泛型类型未指明 8.unused 引用定义了,但是没有被使用 9.all:关于以上所有情况的警告。
3)@SafeVarargs :这是1.7 之后新加入的基本注解. 如例所示,当使用可变数量的参数的时候,而参数的类型又是泛型T的话,就会出现警告。 这个时候,就使用@SafeVarargs来去掉这个警告 ( 具体是啥没搞明白)
@SafeVarargs public staticT getOne(T... elements){ return elements.length>0? elements[0]:null; }
4)@FunctionalInterface:这是Java1.8 新增的注解,用于约定函数式接口。
函数式接口概念: 如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口称为函数式接口。函数式接口其存在的意义,主要是配合Lambda 表达式来使用。 (在使用Lambda表达式的时候的疑惑就是,如果Lambda表达式要实现的接口中不小心定义了多种方法要怎么办)
@FunctionalInterfacepublic interface Run { public void run();}
(2)元注解: 元注解是组成自定义注解的重要器件,其有很多内容,可以参考后面的文章
元注解包括:@Target,@Retention,@Inherited,@Documented,@Repeatable
(3)自定义注解: