【2016-03-01】java注解

经常在代码中看到注解,常用的有@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 注解的基本原理和编程实现


你可能感兴趣的:(【2016-03-01】java注解)