注解(Annotation)
概念:
Java提供的一种原程序中元素关联任何信息和任何元数据的途径和方法。
常见的注解有哪些呢?
JDK中的注解,例如:@Overrid, @Deprecated, @SuppressWarnings等。
第三方注解,例如Spring中的@Autowired, @Service, @Repository, @Table等。
注解的分类:
按照运行机制:
1.源码注解 2.编译时注解 3.运行时注解
源码注解就是只存在与源码中的注解,编译成.class文件之后是不存在的。
编译时注解是源码和.class文件中都存在的注解。
而运行时注解则在运行时刻还起作用,会影响运行时刻的逻辑。
按照来源划分:
1.JDK注解 2.第三方注解 3.自定义注解
要深入学习注解,则必须掌握自定义注解。
要掌握自定义注解,则必须先了解Java为我们提供的元注解和相关定义注解的语法。
元注解:
元注解就是注解的注解,作用就是负责注解其他注解。
Java 5.0定义了4个元注解 1.@Target 2.@Retention 3.@Documented 4.@Inherited
@Target:
@Target说明了Annotation所修饰的对象范围,即:被描述的注解可以用在什么地方
有以下取值:(ElementType)
1.CONSTRUCTOR: 描述构造器
2.FIELD: 描述字段
3.LOCAL_VARIABLE: 描述局部变量
4.METHOD: 描述方法
5.PACKAGE: 描述包
6.PARAMETER: 描述参数
7.TYPE: 描述类、接口(包括注解类型) 或enum声明
@Retention:
@Retention定义了注解的生命周期,也是运行机制。
有以下取值:(RetentionPolicy)
1.SOURCE: 在源文件中有效(即源文件保留)
2.CLASS: 在class文件中有效(即class保留)
3.RUNTIME: 在运行时有效(即运行时保留)
@Documented:
@Documented注解指示了在export导出javadoc的时候会包含注解,即生成文档的时候非常方便。它没有成员。
@Inherited:
@Inherited注解是一个标记注解,没有成员。表明当前这个被注解的类的注解是可继承的(这里有点绕)。
但是如果是方法或者接口interface被注解,那么继承是不起作用的。只对类起作用。
例如:加入我有一个MyAnnotation的自定义注解,并且是@Inherited的。
@MyAnnotation // 可以被继承
class Demo {
@MyAnnotation // 不会被继承
public void aMethod();
}
接下来是自定义注解的语法格式:
public @interface 注解名 {
定义体,即成员
}
其中有如下要求:
1.成员类型是受限的,合法的类型包括基本数据类型,String,Class,Annotation,Enumeration,可以使用default定义默认值。
2.如果注解只有一个成员,那么成员的名字必须取名为value(),使用时忽略参数和=。
3.如果没有成员的话,注解就是标识注解。
简单的实例:
@Target({ElementType.METHOD, ElementType.TYPE}) // 注解的作用范围,方法和类接口。
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期,是运行时周期
@Documented // 导出javadoc时带上这个注解
@Inherited // 是可继承的
public @interface MyAnnotation {
String var1() default ""; // 设置成员默认值,因为注解元素必须有值,所以一般用null或""指示为空。
int var2() default 0;
}
注解的使用:
@MyAnnotation(var1="class", var2=1)
public class Demo {
@MyAnnotation(var1="method")
public void method1() {
...
}
}
主要采用反射机制,获取类,函数或成员的运行时注解信息,从而实现动态控制程序的逻辑的操作。
例子:
自定义注解:MyAnnotaion.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
@MyAnnotation("Class Annotation")
public class BeAnnotatedClass {
@MyAnnotation("Method Annotation")
public void method() {
return;
}
}
解析注解的Main: Main.java
import java.lang.reflect.Method;
public class Main {
public static void main(String args[]) {
/* 1.加载类
* 2.找到类的注解
* 3.拿到注解的值
* 4.找到方法上的注解
* 5.拿到注解的值
* */
try {
// 类
Class c = Class.forName("BeAnnotatedClass");
if (c.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ma = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
System.out.println(ma.value());
}
// 方法
Method[] ms = c.getMethods();
for (Method m: ms) {
if (m.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ma = (MyAnnotation)m.getAnnotation(MyAnnotation.class);
System.out.println(ma.value());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
这样,就可以得到注释的值,可以动态的控制程序的逻辑。