从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。注解,可以看作是对一个 类/方法的一个扩展的模版,每个类/方法按照注解类中的规则,来为类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法中注解的各种参数与值。
那么我们是否曾经思考过,Java注解的本质呢?我们可以把注解看作是一个方法的一个扩展的模板,但其本质并不是,下面我们就直达Java注解的本质。
「java.lang.annotation.Annotation」接口中有这么一句话,用来描述『注解』。
The common interface extended by all annotation types(所有的注解类型都继承自这个普通的接口)
这句话有点抽象,但却说出了注解的本质。我们看一个 JDK 内置注解的定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
这是注解 @Override 的定义,其实它本质上就是:
public interface Override extends Annotation{
}
没错,注解的本质就是一个继承了 Annotation 接口的接口。有关这一点,你可以去反编译任意一个注解类,你会得到结果的。
一个注解准确意义上来说,只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释都不如。
而解析一个类或者方法的注解往往有两种形式,一种是编译期直接的扫描,一种是运行期反射。反射的事情我们待会说,而编译器的扫描指的是编译器在对 java 代码编译字节码的过程中会检测到某个类或者方法被一些注解修饰,这时它就会对于这些注解进行某些处理。
典型的就是注解 @Override,一旦编译器检测到某个方法被修饰了 @Override 注解,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。
这一种情况只适用于那些编译器已经熟知的注解类,比如 JDK 内置的几个注解,而你自定义的注解,编译器是不知道你这个注解的作用的,当然也不知道该如何处理,往往只是会根据该注解的作用范围来选择是否编译进字节码文件,仅此而已。
看完了本文,我们是否找到了自己想要的真相呢?Java注解的本质和你想的是否一样呢?这样其实都不重要,重要的是我们能够掌握Java注解的本质,并合理地使用各种Java注解,这一点在动力节点在线的视频课程里讲的很好,有时间的小伙伴可以抽空学习一番。
提枪策马乘胜追击04-21 20:01
代码小兵92504-17 16:07
代码小兵98804-25 13:57
杨晶珍05-11 14:54