经常在代码中看到注解,常用的有@Override、@Deprecated、Spring注解。
@Override代码如下:
package java.lang; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
Override里面很干净,什么都没有,但是外面有。
涉及到了两个元注解:
@Target :可望文生义,该注解使用在哪种类型的程序元素上的。
@Retention:定义该注解的生命周期,默认为RetentionPolicy.CLASS。
RetentionPolicy.SOURCE:在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。 RetentionPolicy.CLASS:在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。 RetentionPolicy.RUNTIME:始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
查api doc,发现还有另外两种元注解:
@Documented:注解是否将包含在JavaDoc中
@Inherited:是否允许子类继承该注解
另外,还发现了一个Annotation接口:
package java.lang.annotation; public interface Annotation { boolean equals(Object obj); int hashCode(); Class<? extends Annotation> annotationType(); }
此接口功能如下(虽然有点绕,但是说的还是挺清楚地):
1、任何注解都继承了此接口;
2、通过 xxInterface extends Annotation方式继承的不声明注解;
3、此接口自己没有声明注解。
从这个知乎问题知道,注解反编译之后实际上继承了Annotation。
言归正传,看过了@Override的代码,会产生2个疑问:
1、@Override的功能(检查在父类中有一个相同签名的函数)是谁来完成的?
2、如何自定义一个注解?
我们先说第二个问题~
一、如何自定义一个Annotation?
简单如@Retention,发现Retention可以自己注解自己,这不算犯规。
package java.lang.annotation; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value(); }
自定义代码(引自refer2链接):
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation { int count() default 1; // 默认是public,default不是必须的,方法必须有返回值; } @TestAnnotation(count = 0x7fffffff) public class TestMain { public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException { TestAnnotation annotation = TestMain.class.getAnnotation(TestAnnotation.class); System.out.println(annotation.count()); System.in.read(); } }
refer3里有个Filed的例子,这个博客被转的还蛮多的。
二、@Override的功能是谁来完成的?
现在的java IDE都是自动编译的,编译的时候就可以检查是否正确的Override了父类的方法了~
PS: jvm是如何选择@Override的方法的?
看了一些博客之后,大概明白了。由于继承的存在,变量具有“静态类型”和“实际类型”,静态类型在编译器确定,实际类型在运行期确定,执行的时候调用实际类型的Override的方法即可。
Override和Overload的底层实现叫做“分派”(原谅自己第一次见到这个词)。发现Override是jvm的一个叫“动态分派”的过程完成的,与之相对的静态分派是重载(Overload)。除此之外还有多分派、单分派这对术语。
三、相关问题
1、Spring中使用注解注册Bean;
2、XML vs. Annotation;
refer:
1、Java中的注解是如何工作的?
2、java注解是怎么实现的?
3、java 注解的基本原理和编程实现