这篇文章将会带领你了解Java注解,注解的使用,注解的解析,利用反射解析运行时注解,相信有一定Java基础的小伙伴一定会接触大量的注解,Spring , Hibernate , MyBatis等著名的框架也有很多关于注解方面的应用,对于注解的使用小伙伴们应该一点都不陌生,那么如何自定义注解呢?学会自定义注解有什么好处呢?
下面就随笔者进入注解的世界
注解的作用
很多小伙伴在学习注解之前,都不知道学习注解到底可以用来干什么,可以给自身带来什么好处,那么在这里,笔者描述学习注解的几点好处
用过Hibernate的小伙伴,应该使用过Hibernate的配置文件来描述ORM(数据库关系映射),Hibernate实现此功能除了写配置文件之外,当然还包含注解,那么第一个好处就是,注解可以替代配置文件完成对某些功能的描述,减少程序配置
在没有配置文件的情况下,我们去观察代码,并不需要同时打开两个文件来观察这个字段到底对应数据库的哪个列,减少了程序繁琐性,使得代码更加清晰易懂
目前市面上流行的框架基本上都包含了注解配置,那么针对于开源项目,我们在阅读项目代码时,不懂注解如何实现,真的是举步难坚,所以,学习注解也可以加强我们对开源项目源码的解读
最重要的一点,会使用注解和会自定义注解完全是两码事,我的意思是,让别人可以高看你一眼(zhuang bi)
了解注解
注解是Java1.5,JDK5.0引用的技术,与类,接口,枚举处于同一层次 。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释 。
在Java中,自带了三种注解,这三种注解存在于java.lang包中,首先我们讲一讲这些注解
Override——它的作用是对覆盖超类中方法的方法进行标记,如果被标记的类并没有实际覆盖超类,则编译器会发出错误警告。
很常见的一个注解,了解JavaOOP的小伙伴这个注解应该较为常用,告诉编译器,我这个方法是重写了父类方法,当然如果你的方法并没有实际重写父类方法时,那么编译器就会显示警告信息
Deprecated——它的作用是对不应该再使用的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息
当一个方法名或者类名上面此注解之后,编译器会认为这个方法属于过期方法,明显的区别在于类名或者方法名上会画一道删除线,标识过期方法不影响方法的继续使用
SuppressWarnings——这个仅仅是告诉编译器忽略特定的警告信息,例如在泛型中使用原生数据类型
例如我们在使用一些以Deprecated注解的方法时,编译器会提出黄线警告,那么只要在使用的地方加上@SuppressWarnings(“deprecation”)就可以使编译器忽略这个警告
此注释常用的参数值有 : deprecation(忽略使用过时类或者方法),unchecked(忽略执行了未检查装换时警告) , fallthrough(忽略switch直接指向到下一个case块没有break警告),path(忽略类路径,源文件路径中有不存在路径时警告),serial(忽略可序列化类中没有serialVersionUID时的警告),finally(任何finally不能正常执行时的警告),all(以上所有)
自定义注解须知
首先,自定义注解我们必须了解四个元注解,什么是元注解?元注解指作用于注解之上的元数据或者元信息,简单通俗的讲,元注解就是注解的注解 .
Documented——指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API 。
Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
Retention——指明在什么级别显示此注解
Target——指明该类型的注解可以注解的程序元素的范围
Documented与Inherited是典型的标识性注解,也就是说在注解内部并没有成员变量,没有成员变量的注解称为标识注解
Target主要的参数类型包括以下几种
ElementType.TYPE 用于类,接口,枚举但不能是注解
ElementType.FIELD 作用于字段,包含枚举值
ElementType.METHOD 作用于方法,不包含构造方法
ElementType.PARAMETER 作用于方法的参数
ElementType.CONSTRUCTOR 作用于构造方法
ElementType.LOCAL_VERIABLE 作用于本地变量或者catch语句
ElementType.ANNOTATION_TYPE 作用于注解
ElementType.PACKAGE 作用于包
Retention主要的参数类型包括以下几种
RetentionPolicy.SOURCE 注解存在于源代码中,编译时会被抛弃
RetentionPolicy.CLASS 注解会被编译到class文件中,但是JVM会忽略
RetentionPolicy.RUNTIME JVM会读取注解,同时会保存到class文件中
代码:
/*
* 注解
* 1.JDK提供的常用的注解
* @Override:限定重写父类方法,该注释只能用于方法
* @Deprecate:用于表示某个程序(类,方法等)已过时
* @SuppressWarnings:抑制编译器警告
* 2.如何自定义一个注解
* 3.元注解
*/
public class TestAnnotation {
public static void main(String[] args) {
Person p = new Student();
p.walk();
@SuppressWarnings({ "rawtypes", "unused" })
List list = new ArrayList();
@SuppressWarnings("unused")
int i = 10;
// System.out.println(i);
}
}
@MyAnnotation("chai")
class Student extends Person{
@Override
public void walk() {
System.out.println("学生走路");
}
@MyAnnotation("chai")
@Override
public void eat() {
System.out.println("学生吃饭");
}
}
@Deprecated
class Person{
String name;
int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void walk(){
System.out.println("走路");
}
@Deprecated
public void eat(){
System.out.println("吃饭");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
/*
* 自定义注解
*/
@Target({TYPE,FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation {
String value() ;
}