一、注解按照运行机制分类:
源码注解:注解只在源码中存在,.class文件就没了
编译时注解:注解在源码和.class文件里都存在(@Override、@Deprecate)
运行时注解:程序运行时还起作用(@Autowired)
二、注解按照使用的方式和用途分类。
(1)内建注解
又称为基本注解,位于java.lang包下。
内建注解有三个:
1、检验重写父类方法:@Override
2、标识方法已经过时:@Deprecated
3、取消编译器警告:@SurppressWarnings
(2)元注解
元注解就是在注解上添加的注解。
位置:元注解位于java.lang.annotation子包中。
作用:用于修饰其他注解。
元注解有四个:@Retention,@Target,@Documented,@Inherited
(3)自定义注解
需要用到关键字@interface来定义
三、自定义注解
/**
* @author: lizhilong
* @date: 2017-12-05 10:50:54
*/
// 元注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Sign {
// 成员以无参无异常的方式声明
String sign();
String author() default "";
int age() default 18;
}
注意:
1、成员类型只能是基本类型、String、Class、Annotation、Enumeration这几个
2、如果注解只有一个成员,则成员名必须(约定俗成)取名为value()
3、注解可以没有成员,没有成员的注解成为标识注解
4、如果成员没有默认值,则使用的时候必须要填
四、元注解的作用:
@Retention:用来描述被修饰的注解的生命周期。
@Target:用于指定被修饰的注解的适用范围,即被修饰的注解可以用来修饰哪些程序元素。
@Documented:用于指定被修饰的注解将被javadoc工具提取成文档。
@Inherited:用于指定被@Inherited修饰的注解具有继承性。
@Retention 中参数
@Retention(RetentionPolicy.SOURCE):注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS):默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME):注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target中参数
@Target(ElementType.TYPE): 接口、类、枚举、注解
@Target(ElementType.FIELD): 字段、枚举的常量
@Target(ElementType.METHOD): 方法
@Target(ElementType.PARAMETER): 方法参数
@Target(ElementType.CONSTRUCTOR): 构造函数
@Target(ElementType.LOCAL_VARIABLE): 局部变量
@Target(ElementType.ANNOTATION_TYPE): 注解
@Target(ElementType.PACKAGE): 包
五、注解的使用
自定义注解使用的类:
/**
* @author: lizhilong
* @date: 2017-12-05 16:58:29
*/
@Sign(author = "lizhilong", sign = "class sign")
public class Teacher implements Person {
@Override
@Sign(author = "lizhilong", sign = "method sign")
public void eat() {
System.out.println("吃了....");
}
}
注解获取:
package vip.lizhilong.lambda.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.junit.Test;
import vip.lizhilong.lambda.annotation.Sign;
/**
* @author: lizhilong
* @date: 2017-12-05 17:02:12
*/
public class AnnotationTest {
@SuppressWarnings({"rawtypes", "unchecked"})
@Test
public void Test(){
try {
// 1.使用类加载器
Class clazz = Class.forName("vip.lizhilong.lambda.impl.Teacher");
// 2.找到类上的注解(两种)
// 第一种方式
boolean isExit = clazz.isAnnotationPresent(Sign.class);
if (isExit) {
// 3.拿到注解实例
Sign sign = (Sign)clazz.getAnnotation(Sign.class);
System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
}
// 第二种方式
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
// instanceof 判断是否为父子关系,也可以判断类型
if (annotation instanceof Sign) {
Sign sign = (Sign) annotation;
System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
}
}
// 4.找到方法上的注解
Method[] methods = clazz.getMethods();
for (Method method : methods) {
isExit = method.isAnnotationPresent(Sign.class);
if (isExit) {
Sign sign = method.getAnnotation(Sign.class);
System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
打印结果
lizhilong----class sign----18
lizhilong----class sign----18
lizhilong----method sign----18
至此注解的创建和使用的基本方式就这么多,
下篇会讲注解在项目中的使用
如何在在项目中使用自定义注解