一、注解的用处
1、生成文档,例如方法上的注解:@param @return;
2、跟踪代码依赖性,代替文件配置功能:servlet3.0 版本的 @webservlet(name = "hello", urlPatterns = "/getInfo"),可以代替传统的 web.xml 中的配置:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>packageName.className</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/getInfo</url-pattern>
</servlet-mapping>
3、进行格式的检查,子类继承父类,重写父类方法的 @override 注解。
二、注解的原理
注解本质是继承了 Annotation 的特殊接口,具体的实现是 Java 运行时生成的动态代理类,通过反射的方式获取注解时,返回的是 Java 运行时生成的动态代理对象 $Proxy1,通过代理对象调用自定义注解的方法,最终调用 AnnotationInvocationHandler 的 invoke() 方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。
三、元注解
自定义注解的时候需要使用到元注解:
@Target:表示注解用于什么地方,默认全部
· CONSTRUCTOR:用于构造器;
· FIELD:成员变量、对象、属性;
· LOCAL_VARIABLE:用于局部变量;
· METHOD:方法;
· PACKAGE:包;
· PARAMETER:参数;
· TYPE:类、接口。
@Retention:定义注解的生命周期
· SOURCE:在源码有效,编译后丢弃,即不会写入字节码文件;
· CLASS:在字节码中有效,类加载时丢弃(默认);
· RUNTIME:始终有效,可以使用反射来获取注解信息。
@Document:是否将注解信息添加到 Java 文档中
@Inherited:是否可被子类继承
Demo
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitInfo {
public enum Color { RED, GREEN, BLUE };
Color fruitColor() default Color.RED;
String name() default "none";
}
public class Apple {
@FruitInfo(fruitColor = Color.RED, name = "123-apple")
private String appleInfo;
public String getAppleColor() {
return appleInfo;
}
public void setAppleColor(String appleColor) {
this.appleInfo = appleColor;
}
@Override
public String toString() {
return "Apple [appleInfo=" + appleInfo + "]";
}
}
测试:
public class FruitRun {
public static void main(String[] args) {
Field[] fields = Apple.class.getDeclaredFields();
for (Field field : fields) {
FruitInfo fruitInfo = field.getAnnotation(FruitInfo.class);
System.err.println("水果信息:" + fruitInfo.fruitColor() + " - " + fruitInfo.name());
}
}
}
运行结果:水果信息:RED - 123-apple