自定义注解
注解
目录
一、注解 Annotation
Annotation是从JDK5.0开始引入的新技术
Annotation的作用
不是程序本身,可以对程序作出解释(这一点和注释(comment)没什么区别)
可以被其他程序(比如:编译器等)读取
Annotation的格式:
注解是以"@注释名"在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value="unchecked").
Annotation在哪里使用?
可以附加在ackage,class,method,field 等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问
二、内置注解
-
@Override:定义在java.lang.Override 中,此注释只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明.
-
@Deprecated:定义在jaya.lang.Deprecated中,此注释可以用于修饰方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择
-
@SuppressWarnings:定义在java.ang.SuppressWarnings中,用来抑制编译时的警告信息口 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的我们选择性的使用就好了
-
@SuppressWarnings("all")
-
@SuppressWarnings("unchecked")V
-
@SuppressWarnings(value=f"unchecked","deprecation"
-
.....
-
三、元注解
元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明。
这些类型和它们所支持的类在java.lang.annotation包,中可以找到.(@Target,@Retention@Documented ,@inherited )
@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
SOURCE<CLASS <RUNTIME)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
测试元注解
/**
* 测试元注解
* @author zhumq
*/
@MyAnnotation
public class myAnnotationTest {
@MyAnnotation
public void test() {
}
}
// 自定义一个注解
// Target 表示元注解可以注解到哪些元素上
@Target(value ={ElementType.METHOD ,ElementType.TYPE})
// Retention 表示注解保留到哪个阶段,在什么地方还有效
// runtime>class>source
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
// Documented 表示注解是否可以生成在Java Doc文档中
@Documented
// Inherited 表示注解是否可以继承
@Inherited
@interface MyAnnotation {
}
四、自定义注解
使用 @intrface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析
@ interface用来声明一个注解,格式:public @ interface 注解名{定义内容}
可以通过default来声明参数的默认
如果只有一个参数成员,一般参数名为value
注解元素必须要有值,我们定义注解元素时,经常使用空字符串/0作为默认值
测试自定义注解
package com.dev.springBootDemo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.time.temporal.ValueRange;
/**
* 自定义注解
* @author zhumq
* @date 2024/7/1 0:33
*/
public class MyAnnotationTest02 {
// 进行赋值,若无,则需要有默认值
@MyAnnotation02(name = "zhumq",schools = {"清华大学","北京大学"})
// 如果只有一个参数,value可以省略 且必须是value
@MyAnnotation03("zhumq")
public void test(){
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation02 {
// 注解的参数:参数类型 参数名 ();
String name() default "";
int age() default 0;
int id() default -1; // 如果默认值为-1,则代表不存在
String[] schools() ;
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation03 {
String value();
}
五、反编译软件 XJad.exe
六、注解的解析
什么是注解的解析?
- 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
如何解析注解?
- 指导思想:要解析谁上面的注解,就应该先拿到谁。
- 比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解。
- 比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
- Class 、Method、Field,Constructor、都实现了AnnotatedElement接口,它们都拥有解析注解的能力。
七、解析注解案例
package com.itheima.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author zhumq
* @date 2024/7/2 0:08
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {
String value();
double aaa() default 100;
String[] bbb();
}
package com.itheima.annotation;
/**
* @author zhumq
* @date 2024/7/2 0:10
*/
@MyTest4(value = "张三",aaa = 99.6, bbb = {"李四","王五"})
public class Demo {
@MyTest4(value = "牛魔王",aaa = 99.7, bbb = {"周伯通","李逵"})
public void test1(){}
}
进行解析应用
package com.itheima.annotation;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author zhumq
* @date 2024/7/2 0:13
*/
public class AnnotationTest3 {
@Test
public void parseClass() {
// 1.获取class对象
Class c = Demo.class;
// 2.解析类上的注解
// 判断类上是包含了某个注解
if (c.isAnnotationPresent(MyTest4.class)) {
MyTest4 myTest4 = (MyTest4) c.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
@Test
public void parseMethod() throws Exception {
// 1.获取class对象
Class c = Demo.class;
Method m = c.getDeclaredMethod("test1");
// 2.解析方法上的注解
// 判断方法上是包含了某个注解
if (m.isAnnotationPresent(MyTest4.class)) {
MyTest4 myTest4 = (MyTest4)m.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
}
张三 99.6 [李四, 王五] 牛魔王 99.7 [周伯通, 李逵]
八、应用场景
自定义一个注解
package com.itheima.annotation2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 注解只能注释方法
@Retention(RetentionPolicy.RUNTIME) // 租界一直存活
public @interface MyTest {
}
实现并测试
package com.itheima.annotation2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author zhumq
* @date 2024/7/2 0:27
*/
public class AnnotationTest4 {
// @MyTest
public void test1(){
System.out.println("===test1===");
}
@MyTest
public void test2(){
System.out.println("===test2===");
}
// @MyTest
public void test3(){
System.out.println("===test3===");
}
@MyTest
public void test4(){
System.out.println("===test4===");
}
public static void main(String[] args) throws Exception {
AnnotationTest4 a = new AnnotationTest4();
// 1.获取class对象
Class c = AnnotationTest4.class;
// 2.获取所有方法
Method[] m = c.getDeclaredMethods();
// 3.便利这个数组中的每个方法,看方法上是否存在MyTest注解,若存在则执行
for (Method method : m) {
if (method.isAnnotationPresent(MyTest.class)) {
// 说明该方法上有这个注解
method.invoke(a);
}
}
}
}
更多推荐
所有评论(0)