balabala: 可以加在加在包,类,字段,方法,方法参数以及局部变量上。 可以获取信息,处理信息(配置文件的替代),校验信息,可以优雅的进行验证,或者对数据进行加工。使用好注解可以使代码更加整洁,阅读代码时可以更好的将注意力放在业务上。
注解
注解的概述
注解是JDK1.5的特性。
注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息。
标记(注解)可以加在包,类,字段,方法,方法参数以及局部变量上。
注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。
注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,以后javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种 标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
注解的作用
注解的作用就是给程序带入参数。框架的配置(框架=代码+配置)。
常用注解
- 编译检查:@Override 用来修饰方法声明。用来告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败
- @Deprecated: 用来表示不赞成使用
- @SuppressWarnings(“all”) 去除波浪线
自定义注解
格式
public @interface 注解名{
}
如:定义一个名为Student的注解
public @interface Student {
}
注解的属性
- 属性的作用: 可以让用户在使用注解时传递参数,让注解的功能更加强大。
- 属性的格式:
格式1:数据类型 属性名();
格式2:数据类型 属性名() default 默认值;
- 属性适用的数据类型
八种基本数据类型(int,float,boolean,byte,double,char,long,short)
String类型,Class类型,枚举类型,注解类型
以上所有类型的一维数组
使用注意事项
如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。
如果属性没有默认值,那么在使用注解时一定要给属性赋值。
特殊属性value
1.当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给属性值,无论value是单值元素还是数组类型。
2. 如果注解中除了value属性还有其他属性,且至少有一个属性没有默认值,则在使用注解给属性赋值时,value属性名不能省略。
注解之元注解
元注解 即在注解定义时指定注解的使用范围
元注解的概述
Java API提供的注解
专门用来定义注解的注解。
任何Java官方提供的非元注解的定义中都使用到了元注解。
常用元注解
@Target()
作用:指明此注解用在哪个位置,如果不写默认是任何地方都可以使用。可选的参数值在枚举类ElemenetType中包括:
TYPE: 用在类,接口上
FIELD:用在成员变量上
METHOD: 用在方法上
PARAMETER:用在参数上
CONSTRUCTOR:用在构造方法上
LOCAL_VARIABLE:用在局部变量
@Retention()
作用:定义该注解的生命周期(有效范围)。可选的参数值在枚举类型RetentionPolicy中包括
SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值。
RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解。
@Inherited 表示注解可以被使用者的子类继承
什么是注解解析
通过Java技术获取注解数据的过程则称为注解解析。
与注解解析相关的接口
Anontation:
所有注解类型的公共接口,类似所有类的父类是Object。AnnotatedElement:
定义了与注解解析相关的方法,常用方法以下几个:boolean isAnnotationPresent(Class annotationClass);
判断当前对象是否有指定的注解,有则返回true,否则返回false。T getAnnotation(Class<T> annotationClass);
获得当前对象上指定的注解对象。Annotation[] getAnnotations();
获得当前对象及其从父类上继承的所有的注解对象。
使用反射获取注解的数据
举个例子
定义 注解 书 声明在方法上
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
// 书名
String name();
// 价格
double price() default 100;
// 多位作者
String[] authors();
}
定义注解 测试value特性 声明在类上
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface testValue{
String value();
}
// 定义 introduce注解 声明在属性上
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Introduce {
String introduce();
}
使用注解
/**
* @author youngchan
* @version V1.0
* @Package com.youngchan.practice.practice
* @date 2020/5/13 21:23
*/
@testValue("测试Value")
public class PracticeAnnotations {
@Introduce(introduce = "少不看红楼")
private String introduce;
@Book(name = "红楼",price = 26,authors ={ "曹雪芹","冒名作家"})
public void setBook(){
}
}
获取注解中内容
public static void reflectionAnnotations(){
Class<PracticeAnnotations> practiceAnnotationsClass = PracticeAnnotations.class;
try {
if(practiceAnnotationsClass.isAnnotationPresent(testValue.class)){
testValue declaredAnnotation =(testValue) practiceAnnotationsClass.getAnnotation(testValue.class);
System.out.println(declaredAnnotation.value());
}else{
System.out.println("没有这个注解");
}
Method setBook = practiceAnnotationsClass.getMethod("setBook");
if(setBook.isAnnotationPresent(Book.class)){
Book book = (Book) setBook.getAnnotation(Book.class);
System.out.println(book.name() +" ~~" + book.price());
Arrays.stream(book.authors()).forEach(System.out::println);
}else {
System.out.println("方法上也没有这个注解");
}
Field introduce = practiceAnnotationsClass.getDeclaredField("introduce");
if (introduce.isAnnotationPresent(Introduce.class)) {
Introduce annotation = introduce.getAnnotation(Introduce.class);
System.out.println(annotation.introduce());
}else {
System.out.println("属性上没有这个注解");
}
} catch (Exception e) {
e.printStackTrace();
}
}
示例2
package com.youngchan.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Type;
/**
* @author youngchan
* @version V1.0
* @Package com.youngchan.annotation
* @date 2022/11/22 19:58
* @Description //自定义注解
*/
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.TYPE,ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public int numInt() default 10;
public String value() ;
public boolean flog() default true;
public float numFLoat() default 10.1f;
}
package com.youngchan.annotation;
/**
* @author youngchan
* @version V1.0
* @Package com.youngchan.annotation
* @date 2022/11/22 20:04
* @Description //使用自定义注解
*/
@MyAnnotation(value = "我的注解类",flog = false,numFLoat = 6.6f)
public class UseAnnotation {
@MyAnnotation(value = "我的成员变量注解",numInt = 1)
private String name;
@MyAnnotation(value = "我的成员变量注解",numInt = 2)
private String phoneNum;
public UseAnnotation() {
}
@MyAnnotation("我的构造方法注解")
public UseAnnotation(String name, String phoneNum) {
this.name = name;
this.phoneNum = phoneNum;
}
@MyAnnotation("我的成员方法注解")
public void testAnnotation(@MyAnnotation("我的参数注解") String message){
@MyAnnotation("我的局部变量注解")
int age =10;
}
}
package com.youngchan.annotation;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* @author youngchan
* @version V1.0
* @Package com.youngchan.annotation
* @date 2022/11/22 20:11
* @Description // 反射 获取 类 成员变量 成员方法 参数 注解
* Class/method/Field.isAnnotationPresent 判断是否有此注解 Class/method/Field .getAnnotation 获得此注解
*/
public class UseAnnotationRun {
private Logger logger = LoggerFactory.getLogger(UseAnnotationRun.class);
@Test
public void testAnnotation() throws ClassNotFoundException {
Class useAnnotationClass = Class.forName("com.youngchan.annotation.UseAnnotation");;
getAnnotationMessageConstractor(useAnnotationClass);
useAnnotationClass.getDeclaredFields();
getAnnotationMessageField(useAnnotationClass.getDeclaredFields());
getAnnotationMessageMethod(useAnnotationClass.getDeclaredMethods());
}
private void getAnnotationMessageMethod(Method[] declaredMethods) {
for (Method method : declaredMethods) {
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value()+"*******"+myAnnotation.numInt()+"*******"+myAnnotation.numFLoat()+"*******"+myAnnotation.flog());
}
for (Parameter parameter : method.getParameters()) {
if (parameter.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = (MyAnnotation)parameter.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value()+"*******"+myAnnotation.numInt()+"*******"+myAnnotation.numFLoat()+"*******"+myAnnotation.flog());
}
}
}
}
private void getAnnotationMessageField(Field[] declaredFields) {
for (Field fiels : declaredFields) {
if (fiels.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = (MyAnnotation)fiels.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value()+"*******"+myAnnotation.numInt()+"*******"+myAnnotation.numFLoat()+"*******"+myAnnotation.flog());
}
}
}
private static void getAnnotationMessageConstractor(Class useAnnotationClass) {
if (useAnnotationClass.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = (MyAnnotation)useAnnotationClass.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value()+"*******"+myAnnotation.numInt()+"*******"+myAnnotation.numFLoat()+"*******"+myAnnotation.flog());
}
}
}