一、系统注解
注解使用@标记,后面跟上注解类型的名称。Java 语言的 java.lang 包中有 3 种内置注解,即@Override、@Deprecated 和@SuppressWarnings,这些注解用来为编译器提供指令。
1、@Override
@Override 用来修饰一个方法,这个方法必须是对父类中的方法的重写。如果一个方法没有重写父类中的方法,在使用这个注解时编译器将提示错误。
在子类中重写父类或接口的方法时,@Override 并不是必须加上的,但是建议使用这个注解。在某些情况下,若修改了父类方法的名字,那么子类的方法将不再属于重写。由于没有@Override,编译器不会发现问题;但是如果有@Override,编译器就会检查注解的方法是否覆盖了父类的方法。
public class SuperOverride {
public void method(){
System.out.println("父类方法");
}
}
public class SubOverride extends SuperOverride{
@Override
public void method(){
System.out.println("子类方法");
}
}
public class Test {
public static void main(String[] args) {
SuperOverride so = new SuperOverride();
so.method();
}
}
2、@Deprecated
可以用来注解不再使用已经过时的类、方法和属性。如果代码使用了@Deprecated 注解的类、方法和属性,编译器会给出警告。
当使用@Deprecated 注解时,建议使用对应的@deprecated JavaDoc 符号说明这个类、方法或属性过时的原因以及它的替代方案。
/**
* @Deprecated这个类存在缺陷,使用新的NewDeprecatedTest类代替它
*/
public class DeprecatedTest{
……//类体
}
3、@SuppressWarnings
@SuppressWamings 用来抑制编译器生成警告信息。它修饰的元素为类、方法、方法参数、属性和局部变量。当一个方法调用了过时的方法或者进行不安全的类型转换时,编译器会生成警告,此时可以为这个方法增加@SuppressWarnings 注解,从而抑制编译器生成警告。
public class SuppressWarningsTest {
public static void main(String[] args) {
@SuppressWarnings(value = {"abcd"})
Deprecated dtest = new Deprecated();
System.out.println(dtest);
}
}
二、自定义注解
1、自定义注解的定义
在定义自定义注解时,不可以继承其他的注解或接口。@interface 只用来声明一个注解,注解中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型。返回值的类型只能是基本类型、Class、String、Enum。可以通过 default关键字声明参数的默认值。
自定义注解的语法格式如下:
[public | final] @interface 注解名
{
注解元素
}
其中,关键字@interface 表示声明一个自定义注解,“注解名”是合法的标识符。“注解元素”是无参数的方法,方法的类型表示注解元素的类型。
注解元素的语法格式如下:
数据类型 注解元素名() [default 默认值];
如果只有一个注解元素,在注解元素名为 value 的情况下,在使用的时候就可以不写出注解元素名,只需要给出注解值即可。在使用自定义注解时,要将自定义注解放在需要注解的前一行或者同一行,并且在自定义注解后的括号中写出注解元素的值。如果使用默认值,则可以不给出注解值。如果只有一个注解元素并且名为 value,只需要给出值,而不需要给出注解元素名
2、注解元素的值
注解元素一定要有确定的值,可以在定义注解时指定它的默认值,也可以在使用注解时指定默认值,非基本类型的注解元素的值不能为 null。因此,经常使用空字符串或 0 作为默认值。
三、元注解
Java 5.0 API 的 java.lang.annotation 包中提供了 4 个标准的元注解类型,即@Target、@Retention、@Documented 和@Inherited。它们的作用是对其他注解类型进行注解。
1、@Target
@Target 指定注解类型所作用的程序元素的种类。若注解类型声明中不存在 Target 元注解,则声明的类型可以用在任一程序元素上;若存在元注解,则编译器强制实施指定的类型限制。
@Target的使用:
1、定义注解Method
import java.lang.annotation.*;
@Target({ElementType.METHOD})
public @interface Method {}
2、定义类,类的使用方法使用注解Method
//Method作用于类上,出错
public class TargetTest{
@Method //作用于方法上,正确
public void testTarget(){
}
}
2、@Retention
@Retention 的作用是指定需要在什么级别保留该注释信息,它用于描述注解的生命周期,即被描述的注解在什么范围内有效。
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Runtime {
}
3、@Ducumented
@Ducumented只是某一类型的注解将通过javadoc和类似的默认工具进行文档化
import java.lang.annotation.*;
@Target({ElementType.FIELD}) //作用于字段
@Retention(RetentionPolicy.RUNTIME) //运行时有效
@Ducumented //生成文档
public @interface Runtime {
}
4、@Inherited
@Inherited的使用:
1、创建注解Inherite
import java.lang.annotation.*;
@Inherited
public @interface Runtime {
String inher();
}
2、将创建的注解应用在父类SuperOverride上
public class SuperOverride{
public void method(){
System.out.println("父类方法");
}
}
四、使用反射处理注解
利用反射可以在运行时动态地获取类的相关信息,例如类的所有方法、属性和构造方法,还可以创建对象、调用方法等。利用反射也可以获取注解的相关信息。
反射是在运行时获取相关信息的,因此要使用反射获取注解的相关信息,这个注解必须是用@Retention(RetentionPolicy.RUNTIME)声明的。
在 JDK API 中的 java.lang,reflect.AnnotatedElement 接口中定义了使用反射读取注解信息的方法,具体
如下:
-
Annotation getAnnotation(Class annotationType):若存在该元素的指定类型的注解,则返回这些注解,否则返回 null
-
Annotation[] getAnnotations():返回此元素上存在的所有注解。
-
Annotation[] getDeclaredAnnotations():返回该元素上已声明的所有注解,否则返回 null。使用该方法可以自由修改返回的数组。
-
isAnnotationPresent(Class annotationType):若指定类型的注解存在于此元素上,则返回 true,否则返回 false。
Class 类、Constructor 类、Field 类、Method 类和 Package 类都实现了 AnnotatedElement 接口,可以通过这些类的实例获取作用于其上的注解以及相关信息。
利用反射获取类和方法上的注解信息:
1、定义注解
2、在类和类中的方法上使用注解
3、利用反射获取类和方法上的注解信息