再论Java注解
一、什么是注解?
注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理
二、为什么要用注解开发?
传统的方式是,通过配置文件(xml文件 )来告诉类是如何运行的,使用注解开发后,通过注解告诉类是如何运行
三、元注解(注解的注解)
-
@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)——包
-
@Retention:注解的保留位置,用于描述注解的生命周期(SOURCE->CLASS -> RUNTIME)
- RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含
- RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得
- RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
-
@Document:说明该注解将被包含在
javadoc
中 -
@Inherited:是一个标识,用来修饰注解
-
作用:如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解
注意:
- 接口用上个@Inherited修饰的注解,其实现类不会继承这个注解
- 父类的方法用了@Inherited修饰的注解,子类也不会继承这个注解
-
四、JDK基本注解
4.1 @Override
重写注解
@Overried是告诉编译器要检查该方法是实现父类的…可以帮我们避免一些低级的错误…
比如,我们在实现equals()方法的时候,把euqals()打错了,那么编译器就会发现该方法并不是实现父类的,与注解@Override冲突,于是就会给予错误
4.2 @Deprecated
过时注解
在Java迭代中,觉得某些方法设计不好,而为了兼容老版本,不能直接抛弃掉,于是加上注解表明过时的,不建议再用
Date对象中的toLocalString()
就被设计为过时的
@Deprecated
public String toLocaleString() {
DateFormat formatter = DateFormat.getDateTimeInstance();
return formatter.format(this);
}
4.3 SuppressWarnings
镇压警告注解
该注解可以抑制编译器给我们提示的安全警告
4.4 @SafeVarargs
Java7 “堆污染”警告注解
在声明具有模糊类型(比如:泛型)的可变参数的构造函数或方法时,Java编译器会报unchecked警告。鉴于这些情况,如果程序员断定声明的构造函数和方法的主体不会对其varargs参数执行潜在的不安全的操作,可使用@SafeVarargs进行标记,这样的话,Java编译器就不会报unchecked警告
4.5 @FunctionalInterface
@FunctionalInterface函数式接口注解
该注解指定该接口是函数式接口
五、自定义注解
需求:给方法或类注入信息
5.1 标记Annotation
没有任何成员变量的注解称作为标记注解,@Overried就是一个标记注解
public @interface MyAnnotation {
}
5.2 元数据Annotation
注解是可以带成员变量的,定义带成员变量的注解叫做元数据Annotation
在注解中定义成员变量,语法类似于声明方法一样….
public @interface MyAnnotation {
String username();
int age();
}
5.3 使用自定义注解
5.3.1 基本使用
给add方法注入username和age这 两个参数
//注解拥有什么属性,在修饰的时候就要给出相对应的值
@MyAnnotation(username = "xiaoming", age = 20)
public void add(String username, int age) {
}
5.3.2 默认值
在注解声明属性的时候给出默认值,这样我们就可以在使用注解的时候省略掉属性赋值
public @interface MyAnnotation {
String username() default "xiaoming";
int age() default 20;
}
使用注解
@MyAnnotation()
public void add(String username, int age) {
}
5.3.3 注解属性为value
有一种特殊的情况,如果注解上只有一个属性,并且属性的名称为value,那么在使用的时候,我们可以不写value,直接赋值给它就行
public @interface MyAnnotation2 {
String value();
}
使用注解
@MyAnnotation2("zhongfucheng")
public void find(String id) {
}
六、总结
-
注入对象的步骤:得到想要注入的对象属性,通过属性得到注解的信息,通过属性的写方法将注解的信息注入到对象上,最后将对象赋给类。
-
注解其实就是两个作用:
- 让编译器检查代码
- 将数据注入到方法、成员变量、类上
-
在JDK中注解分为
- 元Annotaion:在annotaion包下,常用于修饰其他的Annotation定义
- 基本Annotation:在lang包下,用于常用于标记该方法,抑制编译器警告等