Java 自定义注解 笔记总结(油管)
Java系列文章目录
IDEA使用指南
Java泛型总结(快速上手详解)
Java Lambda表达式总结(快速上手详解)
Java Optional容器总结(快速上手图解)
Java 自定义注解笔记总结(油管)
Java 抽象知识笔记总结(油管)
Java 抽象相关知识笔记
文章目录
- Java系列文章目录
- 一、前言
- 二、学习内容:
- 三、问题描述
- 四、解决方案:
- 4.1 自定义注解引入
- 4.2 自定义注解使用
- 4.2.1 自定义注解概念
- 4.2.2 自定义注解内部的属性
- 五、总结:
- 5.1 学习总结:
一、前言
目的:学习自定义注解相关内容
- 对油管博主John讲解的注解相关知识进行笔记总结
二、学习内容:
- 自定义注解的使用
三、问题描述
- 自定义注解没有实践经验
四、解决方案:
4.1 自定义注解引入
主要了解自定义注解如何创建以及如何使用
引入自定义注解的意义:
- 增强可读性:使代码更清晰,便于理解。
- 元编程:运行时动态获取注解信息,调整程序行为。
- 减少重复代码:简化配置和逻辑,提升开发效率。
- 框架集成:与框架(如Spring)自然结合,简化开发。
- 参数验证:验证用户输入的合法性。
- 文档生成:自动生成接口和文档。
- 配置管理:结合逻辑与配置,便于维护。
参考代码如下:
package org.example;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Main {public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {Cat mycat = new Cat("Kitty");Dog mydog = new Dog("Jerry");if (mydog.getClass().isAnnotationPresent(VeryImportant.class)){System.out.println("This is a very important dog!");} else {System.out.println("This is not a very important dog!");}for (Method method :mycat.getClass().getDeclaredMethods()){if (method.isAnnotationPresent(RunImmediately.class)){RunImmediately annotation = method.getAnnotation(RunImmediately.class);for (int i = 0; i < annotation.times(); i++) {method.invoke(mycat);}}}for (Field declaredField : mycat.getClass().getDeclaredFields()) {if (declaredField.isAnnotationPresent(ImportantString.class)){Object value = declaredField.get(mycat);if (value instanceof String){System.out.println(value.toString().toUpperCase());}}}}
}
- 将对这三个分别在类,方法与字段上的注解的使用方法进行讲解
package org.example;
@VeryImportant
public class Cat {@ImportantStringString name;int age;public Cat(String name) {this.name = name;}@RunImmediately(times = 3)public void meow() {System.out.println("Meow");}public void eat() {System.out.println("Eating");}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RunImmediately {int times();
}
@Target({ElementType.TYPE, ElementType.METHOD})
//实际运行时保留此注解,其他代码可以查看这个注释并在运行时通过反射使用他
//Source 开始编译代码前删除这个注释 处理警告
//CLASS 编译过程保留注释 运行时抛弃
@Retention(RetentionPolicy.RUNTIME)
public @interface VeryImportant {}
Dog是参考类
- 我们学习使用像下面这样的自定义注解
4.2 自定义注解使用
4.2.1 自定义注解概念
自定义注解在编程中主要用于提供额外的信息或元数据,它们并不直接参与程序的运行,而是供编译器、构建工具或其他处理程序在编译期间或运行时解析。
使用场景:
- 增强代码可读性:通过注解,开发者可以为特定代码块添加上下文相关的描述,帮助其他人更好地理解代码的功能。
- 配置信息传递:在框架或库中,注解可以作为配置选项,用于指定组件的行为、路径或者其他需要动态设置的属性。
- AOP(面向切面编程)支持:一些注解用于通知AOP框架进行切面的插入,比如@AspectJ注解。
- 元数据收集:注解可以帮助系统收集关于代码结构、依赖关系等非功能性信息,便于分析、调试和性能优化。
- 未来扩展:如果需要为现有代码预留扩展空间,自定义注解可以避免硬编码,方便后续修改。
主要学习下面两个元注解:
@Target 定义注解作用的位置
- ElementType.ANNOTATION_TYPE: 说明该注解只能应用于其他注解类型。
- ElementType.FIELD: 用于字段(变量)上。
- ElementType.METHOD: 用于方法上。
- ElementType.PARAMETER: 用于方法参数上。
- ElementType.CONSTRUCTOR: 用于构造函数上。
- ElementType.TYPE: 用于类、接口或异常声明上。
- ElementType.PACKAGE: 用于包上。
- ElementType.LOCAL_VARIABLE: 用于局部变量上。
- ElementType.MEMBER_CLASS: 用于成员内部类上。
@Retention 定义了注解应该在哪些级别保留其有效性
-
RUNTIME: 表示该注解在运行时仍然可见,并且可以通过反射API获取到。
-
SOURCE: 只在源代码级别有效,编译后会被丢弃。这种类型的注解通常用于编译器插件或生成其他源代码的时候。
-
CLASS: 仅在类加载时生效,在类加载完成并初始化后就不再可用。这意味着只有类文件级别的注解才会被保留。
- 如果没有ElementType.METHOD就会报错
- 观察结果
4.2.2 自定义注解内部的属性
- 观察可知自定义注解里面参数是函数形式的
如果没有默认值则使用的时候必须写出
- 同理关于字段的注解
五、总结:
5.1 学习总结:
- 注解的定义
自定义注解使用@interface关键字进行定义,并可以包含一些成员方法,通常用于定义额外的参数。
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) // 指定注解的保留策略
public @interface MyAnnotation { String value() default ""; // 默认值 int number() default 0; // 另一个属性
}
- 注解的保留策略
RetentionPolicy.SOURCE:注解只会保留在源代码中,编译后会被丢弃。
RetentionPolicy.CLASS:注解会被保留在class文件中,但在运行时不可用。
RetentionPolicy.RUNTIME:注解会被保留在class文件中,在运行时可以通过反射读取。
- 注解的使用
可以将自定义注解应用于类、方法、字段、参数等。
@MyAnnotation(value = "example", number = 5)
public class MyClass { @MyAnnotation(value = "method") public void myMethod() { }
}
- 读取注解
可以通过Java反射机制读取注解的信息。
import java.lang.reflect.Method; public class AnnotationProcessor { public static void main(String[] args) { Class<MyClass> obj = MyClass.class; // 读取类的注解 if (obj.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = obj.getAnnotation(MyAnnotation.class); System.out.println("Class Annotation: " + annotation.value() + ", " + annotation.number()); } // 读取方法的注解 try { Method method = obj.getMethod("myMethod"); if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); System.out.println("Method Annotation: " + annotation.value()); } } catch (NoSuchMethodException e) { e.printStackTrace(); } }
}
- 注解的元注解
在定义自定义注解时,可以使用元注解来指定注解的特性,常见的元注解有:
@Retention:指定注解的保留策略。
@Target:指定注解可以应用在什么地方(类、方法、字段等)。
@Documented:表明将注解包含在JavaDoc中。
@Inherited:允许子类继承超类的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Target; @Target(ElementType.METHOD) // 该注解只能用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo { String author() default "unknown"; String date(); int revision() default 1;
}
- 注解示例
以下是一个简单的自定义注解示例,展示了如何定义和应用注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test { String value() default "default test";
}
应用示例:public class Example { @Test(value = "This is a test method") public void testMethod() { System.out.println("Executing test method."); }
}
(后续有遇到问题再添加)
声明:如本内容中存在错误或不准确之处,欢迎指正。转载时请注明原作者信息(麻辣香蝈蝈)。