Java注解和反射是很基础的Java知识了,为何还要讲它呢?因为我在面试应聘者的过程中,发现不少面试者很少使用过注解和反射,甚至有人只能说出@Override这一个注解。我建议大家还是尽量能在开发中使用注解和反射,有时候使用它们能让你事半功倍,简化代码提高编码的效率。很多优秀的框架都基本使用了注解和反射,在Spring AOP中,就把注解和反射用得淋漓尽致。
什么是注解Java注解(Annotation)亦叫Java标注,是JDK5.0开始引入的一种注释机制。 注解可以用在类、接口,方法、变量、参数以及包等之上。注解可以设置存在于不同的生命周期中,例如SOURCE(源码中),CLASS(Class文件中,默认是此保留级别),RUNTIME(运行期中)。
注解以@注解名的形式存在于代码中,Java中内置了一些注解,例如@Override,当然我们也可以自定义注解。注解也可以有参数,例如@MyAnnotation(value = "陈皮")。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }那注解有什么作用呢?其一是作为一种辅助信息,可以对程序做出一些解释,例如@Override注解作用于方法上,表示此方法是重写了父类的方法。其二,注解可以被其他程序读取,例如编译器,例如编译器会对被@Override注解的方法检测判断方法名和参数等是否与父类相同,否则会编译报错;而且在运行期可以通过反射机制访问某些注解信息。
内置注解Java中有10个内置注解,其中6个注解是作用在代码上的,4个注解是负责注解其他注解的(即元注解),元注解提供对其他注解的类型说明。
注解 作用 作用范围@Override 检查该方法是否是重写方法。如果其继承的父类或者实现的接口中并没有该方法时,会报编译错误。 作用在代码上
@Deprecated 标记表示过时的,不推荐使用。可以用于修饰方法,属性,类。如果使用被此注解修饰的方法,属性或类,会报编译警告。 作用在代码上
@SuppressWarnings 告诉编译器忽略注解中声明的警告。 作用在代码上
@SafeVarargs Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。 作用在代码上
@FunctionalInterface Java 8开始支持,标识一个匿名函数或函数式接口。 作用在代码上
@Repeatable Java 8开始支持,标识某注解可以在同一个声明上使用多次。 作用在代码上
@Retention 标识这个注解的保存级别,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。包含关系runtime>class>source。 作用在其他注解上,即元注解
@Documented 标记这些注解是否包含在用户文档中javadoc。 作用在其他注解上,即元注解
@Target 标记某个注解的使用范围,例如作用方法上,类上,属性上等等。如果注解未使用@Target,则注解可以用于任何元素上。 作用在其他注解上,即元注解
@Inherited 说明子类可以继承父类中的此注解,但这不是真的继承,而是可以让子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解 作用在其他注解上,即元注解
自定义注解
使用@interface关键字自定义注解,其实底层就是定义了一个接口,而且自动继承java.lang.annotation.Annotation接口。
我们自定义一个注解如下:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface MyAnnotation { String value(); }我们使用命令javap反编译我们定义的MyAnnotation注解的class文件,结果显示如下。虽然注解隐式继承了Annotation接口,但是Java不允许我们显示通过extends关键字继承Annotation接口甚至其他接口,否则编译报错。
D:\>javap MyAnnotation.class Compiled from "MyAnnotation.java" public interface com.nobody.MyAnnotation extends java.lang.annotation.Annotation { public abstract java.lang.String value(); }注解的定义内容如下:
格式为public @interface 注解名 {定义内容}
内部的每一个方法实际是声明了一个参数,方法的名称就是参数的名称。
返回值类型就是参数的类型,而且返回值类型只能是基本类型(int,float,long,short,boolean,byte,double,char),Class,String,enum,Annotation以及上述类型的数组形式。