注解(Annotation)是一种标记,注解可以使用在源码中
注解可以使用在以下的位置
当你在程序中使用了注解,编译器、DE或者程序可以通过反射来获取注解相关的信息,然后根据业务逻辑或者相关需求实现一些功能。
之前使用过的注解:
后期学习框架时会使用到框架提供的很多注解。
注解可以包含属性,定义属性的格式:属性类型 属性名{}
为了让大家理解注解的属性,理解成接口的抽象方法,它有返回值,没有参数。
package com.itheima.demo;
/**
* 我的注解测试
*
* @author YZH
* @date 2023/12/20
*/
public @interface MyTest {
}
注解的属性类型有限制的,只能使用如下的数据类型
自定义注解-带有属性
package com.itheima.demo;
/**
* 表
*自定义注解,带有属性
* @author YZH
* @date 2023/12/20
*/
public @interface Table {
/**
* 表的编号
*
* @return long
*/
long id();
/**
* 表名
*
* @return {@link String}
*/
String name();
/**
* 表名的前缀
*
* @return {@link String}
*/
String prefix();
}
1.不带属性的
package com.itheima.maven.annotation;
import javax.xml.crypto.Data;
import java.sql.Date;
/**
* 测试注解
*
* @author YZH
* @date 2023/12/20
*/
// 在类上使用
@MyTest
public class MyTestAnnotation {
// 在构造方法上使用
@MyTest
MyTestAnnotation(){}
// 在方法上使用
@MyTest
public void showTime(@MyTest String string){
// 在局部变量上使用
@MyTest
String str = "111";
System.out.println(str);
}
}
2.带属性的注解
注意:如果注解带有属性,所有属性都要赋值
package com.itheima.maven.annotation;
/**
* 表注释使用测试
*自定义注解的使用-带属性
* @author YZH
* @date 2023/12/20
*/
public class TableAnnotationUsageTest {
}
@Table(id=1,name = "employee",prefix = "tbl_")
class Employee{
}
4.注解的属性可以有默认值,默认值的格式属性类型属性名(default默认值;String prefix() default "tbl_";
之前自定义的注解在任何地方都可以使用,通过元注解显示注解使用的位置
元注解就是在注解之上使用的注解,其作用就是为了标记自定义注解。
元注解有两个
Target 表示注解可以作用在什么位置上,默认就是任何位置
package com.itheima.maven.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
* 自定义注解
*注解只能用在方法上
* @author YZH
* @date 2023/12/20
*/
@Target(ElementType.METHOD)
public @interface Test {
}
etention :定义注解保留到什么阶段,默认是源码阶段
什么阶段指的是Java程序的运行过程的三个阶段:源码阶段、编译阶段、运行阶段
运行阶段包含编译阶段和源码阶段
编译阶段包含源码阶段
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
JDK自带的注解由JDK提供对应的功能。
目前为止自定义的注解没啥功能。因此想要自定义的注解有些功能,得自己通过反射的API去实现。
Class,Method,Filed,Construtor反射的APl都实现了一个接口java.lang.reflect.AnnotatedElement。
AnnotatedElement接口的重要方法
1.获取类上的注解以及注解的属性信息
package com.itheima.maven.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* 表
*自定义注解,带有属性
* @author YZH
* @date 2023/12/20
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
/**
* 表的编号
*
* @return long
*/
long id();
/**
* 表名
*
* @return {@link String}
*/
String name();
/**
* 表名的前缀
*
* @return {@link String}
*/
String prefix() default "tb_";
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
package com.itheima.maven.annotation;
import org.junit.jupiter.api.Test;
/**
* 解析注解
*
* @author YZH
* @date 2023/12/20
*/
public class AnnotationProcessTest {
@Test
public void processTableAnnotation(){
Class employeeClass = Employee.class;
// 获取Employee的注解
Table tableAnnotation = employeeClass.getAnnotation(Table.class);
// 注解的类型信息
System.out.println("注解的类型信息:"+tableAnnotation);
// 获取注解的属性值
System.out.println(tableAnnotation.id());
System.out.println(tableAnnotation.name());
System.out.println(tableAnnotation.prefix());
}
}
2.获取类中成员变量的注解
package com.itheima.maven.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author YZH
* @date 2023/12/20
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name();
}
@Test
public void processColumnAnnotation(){
Class employeeClass = Employee.class;
try {
Field nameFiled = employeeClass.getDeclaredField("name");
Column columnAnnotation = nameFiled.getAnnotation(Column.class);
// 注解的类型信息
System.out.println("注解的类型信息:"+columnAnnotation);
// 获取注解的属性值
System.out.println(columnAnnotation.name());
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}