【Java注释】如何自定义注解以及JDK中的元注解
一,如何自定义注解
1.1 在编译时进行格式检查(JDK内置的三个基本注解)
@Override: 限定重写父类方法, 该注解只能用于方法 @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择 @SuppressWarnings: 抑制编译器警告
1.2 自定义注解:
参照@SuppressWarnings定义
① 注解声明为:@interface
② 内部定义成员,通常使用value表示
③ 可以指定成员的默认值,使用default定义
④ 如果自定义注解没有成员,表明是一个标识作用
举例:内部定义成员默认为“hello”
public @interface MyAnnotation {
String value() default "hello";
}
使用:
一:默认
@MyAnnotation
class Person {
}
二:指定成员
@MyAnnotation(value = "hi")
class Person {
}
如果注解有成员,在使用注解时,需要指明成员的值 自定义注解必须配上注解的信息处理流程(使用反射)才有意义
二:JDK中的元注解
2.1 什么是元注解
JDK 的元 Annotation 用于修饰其他 Annotation 定义
2.2 JDK5.0提供了4个标准的meta-annotation类型
> Retention
> Target
> Documented
> Inherited
2.3 JDK中四种元注解的使用
一:@Retention
@Retention:只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用@Rentention 时必须 为该 value 成员变量指定值:
RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释
RetentionPolicy.CLASS:在class文件中有效(即class保留) , 当运行 Java 程序时, JVM不会保留注解。 这是默认值
RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行 Java 程序时, JVM 会保留注释。程序可以通过反射获取该注释
下面再源代码中查看
首先打开SuppressWarnings
可以看到Retention:指定所修饰的Annotation生命周期
我们再打开枚举类RetentionPolicy
我们可以看到有
SOURCE
CLASS(默认行为)
RUNTIME:只有声明为RUNTIME声明周期的注解,才能通过反射获取
三种变量
二:@Target:
用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于 修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。
我们打开枚举类ElementType可以看到
在自定义注解MyAnnotation中加上
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
并且将 CONSTRUCTOR删掉,
测试如下:
此时我们可以发现MyAnnotation修饰构造器就会报错
简单来说Target:用于指定被修饰的 Annotation 能用于修饰哪些程序元素
自定义注解通过都会指明两个元注解:Retention,Target
下面两种用的较少
三:@Documented:
用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。
定义为Documented的注解必须设置Retention值为RUNTIME。
四:@Inherited
@Inherited: 被它修饰的 Annotation 将具有继承性。如果某个类使用了被@Inherited 修饰的 Annotation, 则其子类将自动具有该注解。
比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解
实际应用中,使用较少
我们怎么证明@Inherited的继承性?
我们可以通过反射获取注解信息 --- 到反射内容时再描述
我们先看一个例子:
注释MyAnnotation代码如下:
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
String value() default "hello";
}
测试:
import org.junit.Test;
import java.lang.annotation.Annotation;
public class AnnotationTest {
@Test
public void testGetAnntation(){
Class studentClass = Student.class;
Annotation[] annotations = studentClass.getAnnotations();
for (int i = 0; i < annotations.length; i++) {
System.out.println(annotations[i]);
}
}
}
@MyAnnotation(value = "hi")
class Person {
private String name;
private int age;
@SuppressWarnings("unused")
int i = 0;
@MyAnnotation
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void walk() {
System.out.println("人说话");
}
public void eat() {
System.out.println("人吃饭");
}
}
interface Info{
void show();
}
class Student extends Person implements Info{
@Override
public void walk() {
System.out.println("学生走路");
}
@Override
public void show() {
}
}
运行结果如下:
如果将Student的父类Person上的@MyAnnotation(value = "hi")去掉运行结果如下:
由此我们可以看出@Inherited的继承性
感谢观看!!!