概述
从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,
这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。
通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
我们可以把注解分为三类:
- 元注解
- JDK注解
- 自定义注解
其中自定义注解我们用的是最多的, 比如各个框架中用的注解就是框架设计者自定义的注解
元注解
描述注解的注解,就5个:
- @Target 注解用在哪里:类上、方法上、属性上
- @Retention 注解的生命周期:源文件中、class文件中、运行中
- @Inherited 允许子注解继承
- @Documented 生成javadoc时会包含注解,不常用
- @Repeatable注解为可重复类型注解,可以在同一个地方多次使用,不常用
@Target ElementType.class
描述注解的使用范围:
- ElementType.ANNOTATION_TYPE 应用于注释类型
- ElementType.CONSTRUCTOR 应用于构造函数
- ElementType.FIELD 应用于字段或属性
- ElementType.LOCAL_VARIABLE 应用于局部变量
- ElementType.METHOD 应用于方法级
- ElementType.PACKAGE 应用于包声明
- ElementType.PARAMETER 应用于方法的参数
- ElementType.TYPE 应用于类的元素
@Retention RetentionPolicy.class
定义了该注解被保留的时间长短,某些注解仅出现在源代码中,而被编译器丢弃;
而另一些却被编译在class文件中; 编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取。
为何要分有没有呢?没有时,反射就拿不到,从而就无法去识别处理。
- SOURCE 在源文件中有效(即源文件保留)
- CLASS 在class文件中有效(即class保留)
- RUNTIME 在运行时有效(即运行时保留)
JDK注解
JDK自带的注解,就5个:
- @Override
- @Deprecated标记就表明这个方法已经过时了,但我就要用,别提示我过期
- @SuppressWarnings(“deprecation”) 忽略警告
- @SafeVarargs jdk1.7出现,堆污染,不常用
- @FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用
自定义注解
- 我们也可以根据自己的需求来定义个性化的注解
- 使用的是@interface 注解名来定义的,主要使用的就是上面的两个元注解 - 除此之外,我们还可以给注解加功能,比如注解的属性:
- 格式:属性类型 属性名(); 比如:int age();
- 注意:定义了注解的普通属性以后,使用注解时必须给属性赋值,格式:@Rice(age=10)
- 如果给属性设置了默认值,那么使用注解时就不需要给属性赋值了,格式:int age() default 0; - 我们还可以给注解添加特殊的属性value,注意这个属性名字必须是value,类型不作限制
- 注意1:特殊属性如果不设置默认值,使用注解时也需要赋值,不过赋值可以简写,比如@Rice(“apple”)
- 特殊属性赋予默认值后,就可以直接使用注解了,赋予默认值的格式:String value() default “apple”;
- 注意2:如果有多个属性,并且都没有赋予默认值,那么使用注解时的格式:@Rice(value=“apple”,age=10)
1.定义注解
//1,定义注解
//1.1,设置注解的使用范围@Target,啥都不写,哪儿都能用
//@Target({ElementType.METHOD})//作用于方法上
//@Target({ElementType.FIELD})//作用于属性上
@Target({ElementType.METHOD , ElementType.PACKAGE})//作用范围
@Retention(RetentionPolicy.SOURCE)//生命周期
@Target({ElementType.TYPE})//作用于类上
@interface Test{
//3,定义属性
int age() default 0;//使用时,必须给age属性赋值,如:age=X。除非设置好默认值。
//()不是参数,也不能写参数,只是特殊语法
//4,特殊属性value
String value() default "";//使用时,必须给value属性赋值,如:X | value=X。除非设置好默认值
}
2.使用注解
//2,使用注解
//@Test
//5,注解的组合属性
@Test(value="",age=0)
class HelloTest{
// @Test(value="",age=0)
String name;
}
3.解析注解
package javapro.spring.annotation;
public class TestAnnotation {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("javapro.spring.annotation.HelloController");
Controller c = clazz.getAnnotation(Controller.class);
if( c != null) {
System.out.println(c);
System.out.println(c.value());
}
}
}