注解初步理解
参考:bilibili动力节点老杜
认识注解
注解是什么
注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
注解怎么写
[修饰符] @interface [注解名]{
}
public @interface MyAnnotation {
}
注解怎么用
@[注解名]
注解可以使用在类,属性,方法甚至注解等上
默认情况下可是使用在任何东西上
@MyAnnotation
public class AnnotationTest {
@MyAnnotation
private int age;
@MyAnnotation
public void test01(@MyAnnotation String str){
@MyAnnotation
int a=0;
}
}
JDK内置重要注解
-
Override
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
@Override注解只能注解方法
@Override这个注解是给编译器参考的和运行阶段没有关系
凡是带有这个注解的方法,编译器会进行编译检查,如果没有重写父类的方法,就会报错 -
Deprecated
表示属性,方法,构造函数等已过时@Documented @Retention(RetentionPolicy.RUNTIME) @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) public @interface Deprecated { }
注解中的属性
我们可以在注解当中定义属性,以下是MyAnnotation的name属性,看着像一个方法,但实际上我们称之为属性name
注解中有属性
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String name();
}
@MyAnnotation(name = "asdas")
public class AnnotationTest {
private int age;
@Deprecated
public void test01(){
int a=0;
}
}
如果一个注解当中有属性,那么必须给属性赋值
注解中属性有默认值
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String name();
int age() default 18;
}
@MyAnnotation(name = "asdas")
public class AnnotationTest {
private int age;
@Deprecated
public void test01(){
int a=0;
}
}
当注解属性有默认值使用该注解时可以不用写属性值
注解属性名是value
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value();
}
@MyAnnotation("hehe")
public class AnnotationTest {
当注解属性名是value并且只有一个属性时可以不用写属性名
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value();
String name();
}
@MyAnnotation(name = "hehe",value = "sad")
public class AnnotationTest {
属性的类型
基本数据类型,枚举以及每种的数组
String value();
String[] values();
int age();
int[] ages();
Class clazz();
Class clazzs();
Session session();
Session[] sessions();
Integer sex();//报错
当注解类型是数组且只有一个元素,大括号可以省略
@MyAnnotation(age=26,names={"zhangsan","lisi"})
...
@MyAnnotation(age=26,names="zhangsan")
...
元注解
什么是元注解
用来标注注解类型的注解称为元注解
常见的元注解
-
@Target
这个注解用来标注被标注的注解可以出现的位置@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); }
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
@Override的元注解@Target(ElementType.METHOD)表示被标注的注解只能出现在方法上
里面的参数可以是枚举类型ElementType的属性
-
@Retention
这个注解用来标注被标注的注解最终保存到哪
@Override的元注解@Retention(RetentionPolicy.SOURCE)
SOURCE,//表示该注解只被保留在java源文件中 CLASS,//表示该注解可以保留在class文件中 RUNTIME//表示该注解可以保留在class文件中,且在运行时可以被反射机制使用
-
@Documented
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Documented { }
用 @Documented 注解修饰的注解类会被 JavaDoc 工具提取成文档。默认情况下,JavaDoc 是不包括注解的,但如果声明注解时指定了 @Documented,就会被 JavaDoc 之类的工具处理,所以注解类型信息就会被包括在生成的帮助文档中。
-
@Inherited
@Inherited 是一个标记注解,用来指定该注解可以被继承。使用 @Inherited 注解的 类,表示这个注解可以被用于该 类的子类。就是说如果某个类使用了被 @Inherited 修饰的注解,则其子类将自动具有该注解。
注解与反射的使用
反射注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)//可以被反射到
public @interface MyAnnotation {
String name() default "cxk";
}
Class clazz = Class.forName("com.example.AnnotationTest");
//判断类上是否有@MyAnnotation
System.out.println(clazz.isAnnotationPresent(MyAnnotation.class));//true
if(clazz.isAnnotationPresent(MyAnnotation.class)){
//获取该注解对象
MyAnnotation myAnnotation=(MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
System.out.println("类上的注解对象"+myAnnotation);//类上的注解对象@com.example.MyAnnotation()
//获取注解对象的属性和调接口没区别
System.out.println(myAnnotation.name());//cxk
}
注解在开发中有什么用
需求:
假设有这样一个注解@Id
这个注解只能出现在类上面,当这个类上有这个注解的时候
要求这个类中必须有一个int类型的id.如果没有这个属性就报异常
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)//可以被反射到
public @interface Id {
}
@Id
public class AnnotationTest {
//private int id;
private Integer id;
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("com.example.AnnotationTest");
if(clazz.isAnnotationPresent(Id.class)){
try {
Field field=clazz.getDeclaredField("id");
if(field.getType()!=int.class){
throw new Exception("id属性不为int");
}
System.out.println("hello world");
} catch (NoSuchFieldException e) {
throw new Exception("id属性不存在");
}
}else{
System.out.println("hello world");
}
}
}
注解在程序中等同于一种标记,如果有这个注解怎么办,如果没有怎么办