当前位置: 首页 > news >正文

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 学习总结:

  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; // 另一个属性  
}  
  1. 注解的保留策略

RetentionPolicy.SOURCE:注解只会保留在源代码中,编译后会被丢弃。
RetentionPolicy.CLASS:注解会被保留在class文件中,但在运行时不可用。
RetentionPolicy.RUNTIME:注解会被保留在class文件中,在运行时可以通过反射读取。

  1. 注解的使用

可以将自定义注解应用于类、方法、字段、参数等。

@MyAnnotation(value = "example", number = 5)  
public class MyClass {  @MyAnnotation(value = "method")  public void myMethod() {  }  
}  
  1. 读取注解

可以通过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();  }  }  
}  
  1. 注解的元注解

在定义自定义注解时,可以使用元注解来指定注解的特性,常见的元注解有:

@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;  
}  
  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.");  }  
}  

(后续有遇到问题再添加)


声明:如本内容中存在错误或不准确之处,欢迎指正。转载时请注明原作者信息(麻辣香蝈蝈)。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Go】通过反射解析对象tag信息,实现简易ORM
  • llama factory 训练 TensorBoard 可视化
  • 【C++】——Vector的模拟实现
  • Golang | Leetcode Golang题解之第324题摆动排序II
  • mysql如何储存大量数据,分库存分表的建议和看法
  • gbd的概念与常用指令
  • 【Linux基础】Linux基本指令(一)
  • 小米教你:2GB内存搞定20亿数据的高效算法
  • 【C++】vector 的模拟实现
  • 从0开始的算法(数据结构和算法)基础(七)
  • Unity Addressables bundle依赖查看和资源重复查看工具
  • linux 多进程搭建webserver
  • MinGW-w64编译安装Acise
  • 维吉尼亚密码加解密实现(python)
  • Android 12系统源码_多屏幕(一)多屏幕设备显示Activity
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • C语言笔记(第一章:C语言编程)
  • express.js的介绍及使用
  • fetch 从初识到应用
  • Netty 4.1 源代码学习:线程模型
  • nfs客户端进程变D,延伸linux的lock
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 基于axios的vue插件,让http请求更简单
  • 马上搞懂 GeoJSON
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 使用Gradle第一次构建Java程序
  • 写给高年级小学生看的《Bash 指南》
  • 终端用户监控:真实用户监控还是模拟监控?
  • 如何在招聘中考核.NET架构师
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #Linux(Source Insight安装及工程建立)
  • #Spring-boot高级
  • (1)(1.13) SiK无线电高级配置(六)
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (转)拼包函数及网络封包的异常处理(含代码)
  • *Django中的Ajax 纯js的书写样式1
  • .axf 转化 .bin文件 的方法
  • .gitignore文件设置了忽略但不生效
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET企业级应用架构设计系列之开场白
  • :“Failed to access IIS metabase”解决方法
  • @SentinelResource详解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [ C++ ] 类和对象( 下 )
  • [Algorithm][动态规划][两个数组的DP][正则表达式匹配][交错字符串][两个字符串的最小ASCII删除和][最长重复子数组]详细讲解
  • [Android]通过PhoneLookup读取所有电话号码
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标