Annotation
注解是JDK 5.0版本引入的新特性,对元数据支持。注解就像一个标签,贴在哪里哪里就有这个标签的特性
- 注解本身并不是程序的一部分,可以对程序进行解释
- 注解可以被其他的程序所读取题
注解的格式
注解以@开头,形式为@注解名
,注解可以有参数,也可以没有参数
- 没有参数的注解,比如lombok的
@Data
注解,直接注解在类上,生成类所有属性的getter和setter方法,还生成equals、canEqual、hashCode、toString 方法 - 有参数的注解,比如
@RequestMapping(value="/books", Method=RequestMethod.GET)
,@RequestMapping
现在可以用诸如@GetMapping
,@PostMapping
,@PutMapping
等代替
内置注解
这个注解用于表示某个类,方法等已过时,或者有了更好的方案可以选用。建议不要用
方法上有@Deprecated
注解,调用该方法的时候会出现中划线, 注解在类上也是一样的情况。
-
3. @SuppressWarnings
这个注解用来抑制编译器的警告,被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告 -
4.@FunctionalInterface
只有一个方法的接口就是函数式接口
接口的方法都是Abstract 和 public的
元注解(meta Annotation)
public enum ElementType {
TYPE, // 用于类和接口
FIELD, // 用于字段
METHOD, // 用于方法
PARAMETER, // 用于方法参数
CONSTRUCTOR, // 用于构造函数
LOCAL_VARIABLE, // 用于本地变量
ANNOTATION_TYPE, // 用于注解
PACKAGE, // 用于包
TYPE_PARAMETER, // 用于类型参数
TYPE_USE, // 用于任何类型
MODULE, // 用于module
}
关于TYPE_PARAMETER和TYPE_USE,大家可能不太熟悉,下面我贴张图大家就理解了
首先定义两个注解
学过泛型的小伙伴应该都看得懂,TYPE_PARAMETER的用法跟泛型有点像
TYPE_USE虽说可以用于任何类型,可以用在方法,类,方法参数等上面。但是如果方法返回值是void就会报错
-
@Retention
这个注解用来定义注解的保留策略- SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被编译器忽略
- CLASS: 注解将会保留在字节码文件,字节码被jvm加载的时候注解会被忽略
- RUNTIME: 注解在字节码呗jvm加载后依然存在
-
@Inherited
先上代码
import java.lang.annotation.*;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@interface IsInherited {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface IsNotInherited {
}
@IsInherited
@IsNotInherited
class BaseClass {
}
class InheritedClass extends BaseClass {
}
@IsInherited
@IsNotInherited
interface BaseInterface {
}
interface InheritedInterface extends BaseInterface {
}
class IInheritedClass implements BaseInterface {
}
public class Demo<T> {
@Test
public void test() {
System.out.println("====== test class ======");
Annotation[] annotations = InheritedClass.class.getAnnotations();
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsInherited.class)));
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsNotInherited.class)));
System.out.println("====== test extends interface ======");
annotations = InheritedInterface.class.getAnnotations();
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsInherited.class)));
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsNotInherited.class)));
System.out.println("====== test implements interface ====== ");
annotations = IInheritedClass.class.getAnnotations();
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsInherited.class)));
System.out.println(Arrays.stream(annotations).anyMatch(item -> item.annotationType().equals(IsNotInherited.class)));
}
}
结果
====== test class ======
true
false
====== test extends interface ======
false
false
====== test implements interface ======
false
false
结论
类继承关系: 子类会继承父类使用的注解中被@Inherited修饰的注解
接口继承关系:无论是实现接口还是继承接口,父接口中的注解无论如何都不会装饰子类或者接口