温州网站建设制作,陈铭生杨昭原型,做网站用那一种语言最好,上海优化网站 优帮云文章目录 介绍定义注解处理注解使用注解 介绍
注解Annotation#xff1a;是放在Java源码的类、方法、字段、参数前的一种特殊注释
注释会被编译器直接忽略#xff0c;注解则可以被编译器打包进入class文件#xff0c;因此#xff0c;注解是一种用作标注的“元数据”。
作… 文章目录 介绍定义注解处理注解使用注解 介绍
注解Annotation是放在Java源码的类、方法、字段、参数前的一种特殊注释
注释会被编译器直接忽略注解则可以被编译器打包进入class文件因此注解是一种用作标注的“元数据”。
作用 1、编译器使用的注解 不会被编译进入.class文件在编译后就被编译器扔掉了
例子 Override让编译器检查该方法是否正确地实现了覆写 SuppressWarnings告诉编译器忽略此处代码产生的警告。 2、由工具处理.class文件使用的注解
3、在程序运行期能够读取的注解它们在加载后一直存在于JVM中这也是最常用的注解。
定义注解时可以定义配置参数可以有默认值。
public class Hello {Check(min0, max100, value55)public int n;Check(value99)public int p;Check(99) // Check(value99)public int x;Checkpublic int y;
}定义注解
使用interface语法来定义注解Annotation
public interface Report {int type() default 0;String level() default info;String value() default ;
}元注解 作用修饰其他注解。
Java中已经定义了一些元注解。
常用的
1、Target
使用Target可以定义Annotation能够被应用于源码的哪些位置
类或接口ElementType.TYPE字段ElementType.FIELD方法ElementType.METHOD构造方法ElementType.CONSTRUCTOR方法参数ElementType.PARAMETER。
Target(ElementType.METHOD)
public interface Report {int type() default 0;String level() default info;String value() default ;
}Target({ElementType.METHOD,ElementType.FIELD
})
public interface Report {...
}2、Retention
Retention定义了Annotation的生命周期
仅编译期RetentionPolicy.SOURCE仅class文件RetentionPolicy.CLASS运行期RetentionPolicy.RUNTIME。
如果Retention不存在则该Annotation默认为CLASS。
3、Repeatable
Repeatable可以定义Annotation是否可重复。
4、Inherited Inherited定义子类是否可继承父类定义的Annotation。
Inherited仅针对Target(ElementType.TYPE)类型的annotation有效并且仅针对class的继承对interface的继承无效
Inherited
Target(ElementType.TYPE)
public interface Report {int type() default 0;String level() default info;String value() default ;
}定义Annotation步骤
1、用interface定义注解
2、添加参数默认值
3、用元注解配置注解
其中必须设置Target和RetentionRetention一般设置为RUNTIME
处理注解
根据Retention的配置
SOURCE类型的注解在编译期就被丢掉了CLASS类型的注解仅保存在class文件中它们不会被加载进JVMRUNTIME类型的注解会被加载进JVM并且在运行期可以被程序读取。
SOURCE类型的注解主要由编译器使用一般只使用不编写。CLASS类型的注解主要由底层工具库使用涉及到class的加载一般很少用到。只有RUNTIME类型的注解不但要使用还经常需要编写。
读取RUNTIME类型注解 注解定义后也是一种class所有的注解都继承自java.lang.annotation.Annotation读取注解需要使用反射API Java提供的使用反射API读取Annotation的方法包括
判断某个注解是否存在于Class、Field、Method或Constructor
Class.isAnnotationPresent(Class)Field.isAnnotationPresent(Class)Method.isAnnotationPresent(Class)Constructor.isAnnotationPresent(Class)
使用反射API读取Annotation
Class.getAnnotation(Class)Field.getAnnotation(Class)Method.getAnnotation(Class)Constructor.getAnnotation(Class)
使用反射API读取Annotation有两种方法。方法一是先判断Annotation是否存在如果存在就直接读取
Class cls Person.class;
if (cls.isAnnotationPresent(Report.class)) {Report report cls.getAnnotation(Report.class);...
}第二种方法是直接读取Annotation如果Annotation不存在将返回null
Class cls Person.class;
Report report cls.getAnnotation(Report.class);
if (report ! null) {...
}要读取方法参数的注解我们先用反射获取Method实例然后读取方法参数的所有注解
public void hello(NotNull Range(max5) String name, NotNull String prefix) {
}// 获取Method实例:
Method m ...
// 获取所有参数的Annotation:
Annotation[][] annos m.getParameterAnnotations();
// 第一个参数索引为0的所有Annotation:
Annotation[] annosOfName annos[0];
for (Annotation anno : annosOfName) {if (anno instanceof Range r) { // Range注解r.max();}if (anno instanceof NotNull n) { // NotNull注解//}
}使用注解
例子
写一个Range注解希望用它来定义一个String字段的规则字段长度满足Range的参数定义
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface Range {int min() default 0;int max() default 255;
}在某个JavaBean中可以使用该注解
public class Person {Range(min1, max20)public String name;Range(max10)public String city;
}但是定义了注解本身对程序逻辑没有任何影响。必须自己编写代码来使用注解。这里编写一个Person实例的检查方法它可以检查Person实例的String字段长度是否满足Range的定义
void check(Person person) throws IllegalArgumentException, ReflectiveOperationException {// 遍历所有Field:for (Field field : person.getClass().getFields()) {// 获取Field定义的Range:Range range field.getAnnotation(Range.class);// 如果Range存在:if (range ! null) {// 获取Field的值:Object value field.get(person);// 如果值是String:if (value instanceof String s) {// 判断值是否满足Range的min/max:if (s.length() range.min() || s.length() range.max()) {throw new IllegalArgumentException(Invalid field: field.getName());}}}}
}例子 只看不知道具体怎么写就看着敲了一遍
Range.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface Range {int min() default 0;int max() default 255;
}Animal.java
public class Animal {Range(min 2, max 20)public String name;Range(min 0, max 8)public int number;public Animal(String name,int number) {this.name name;this.number number;}
}TestAnnotation2.java
import java.lang.reflect.Field;public class TestAnnotation2 {public static void main(String[] args) throws ReflectiveOperationException {Animal animalnew Animal(1,10);check(animal);}static void check(Animal person) throws IllegalArgumentException,ReflectiveOperationException{for(Field field : person.getClass().getFields()){Range rangefield.getAnnotation(Range.class);if(range!null){Object valuefield.get(person);if(value instanceof String){if (((String) value).length() range.min() || ((String) value).length() range.max()) {System.out.println(Invalid field: field.getName());}}if(value instanceof Integer){if ((int)value range.min() || (int)value range.max()) {System.out.println(Invalid field: field.getName());}}}}}
}