手写反射实现读取自定义注解中的属性值

news/2024/11/28 18:56:46/

目录

  • 背景
  • 过程
    • 注解概念
    • 明确自定义注解的边界
      • 1、定义注解:使用 @interface 关键字定义一个新的注解。注解可以包含元素,用于指定注解的属性。
      • 2、使用注解:在适当的地方使用自定义注解。可以将注解应用于类、方法、字段等。
      • 3、解析注解:在程序中通过反射机制解析和处理注解。可以获取注解的属性值,并根据注解的定义执行相应的操作。
    • 手写反射实现自定义注解
  • 结果

背景

凡事我们都要知其然,知其所以然,我们既然要研究反射,就要知道
反射的原理是什么:在Java中,反射(Reflection)是指在运行时获取和操作类的信息的能力。它允许程序在运行时动态地检查类、获取类的属性和方法,并且可以调用类的方法或创建类的实例。
但是他到底是怎么做到运行时获取到信息的呢?我们一起来看一看吧,归根结底,还是匹配字符串,但是是如何匹配的我们还需要考究一下,下面我就手写自定义注解的例子讲解如何使用反射的,并把他手写出来。

过程

注解概念

当应用5W2H方法分析注解时,我们可以按照以下方式来描述注解的作用和含义:

What(什么):注解是一种特殊的标记,用于提供元数据。它可以应用于类、方法、字段等程序元素上,以附加额外的信息。

Why(为什么):注解的目的是为了丰富和增强代码的表达能力和功能。它可以提供额外的元数据,用于编译时检查、运行时处理和自动生成代码等。

Where(在哪里):注解可以应用于各种程序元素,包括类、方法、字段等。具体可以根据注解的定义和目的来决定它可以应用的位置。

When(何时):注解在编码过程中可以随时使用。根据需求,可以在需要注解的代码上使用它们,例如标记过时的方法、指定配置信息等。

Who(谁):注解可以由开发人员或框架进行定义和使用。开发人员可以为自己的代码添加注解,而框架可以使用注解来实现特定的行为或功能。

How(如何):注解通过使用@符号作为前缀,并提供注解名称和可选的参数来声明和使用。开发人员可以自定义注解,并通过反射机制来解析注解并采取相应的操作。

How much(多少):注解的数量和复杂性取决于具体的应用场景和需求。Java提供了一些内置的注解,同时也可以根据需要自定义注解。

明确自定义注解的边界

在Java中,注解(Annotation)是一种用于提供元数据的特殊标记。它可以应用于类、方法、字段等程序元素上,以提供关于这些元素的额外信息。注解本身不会直接影响程序的执行,但可以被编译器、工具和框架等处理,以实现特定的行为或功能。

1、定义注解:使用 @interface 关键字定义一个新的注解。注解可以包含元素,用于指定注解的属性。

// 定义一个自定义注解
public @interface MyAnnotation {String value();int count() default 0;
}

2、使用注解:在适当的地方使用自定义注解。可以将注解应用于类、方法、字段等。

// 使用自定义注解
@MyAnnotation(value = "Hello", count = 5)
public class MyClass {@MyAnnotation("World")private String message;@MyAnnotation(value = "Method")public void myMethod() {// 方法体}
}

3、解析注解:在程序中通过反射机制解析和处理注解。可以获取注解的属性值,并根据注解的定义执行相应的操作。

// 解析注解
Class<?> clazz = MyClass.class;
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
String value = annotation.value();
int count = annotation.count();

手写反射实现自定义注解

我们主要是实现自定义注解步骤的第三步,上述的步骤是使用getAnnotation
方法获取的注解的相关信息,我们现在不使用这个API,自己手写一个实现文本匹配从而实现getAnnotation的效果:

public class Client {public static void main(String[] args) throws IOException, NoSuchFieldException, ClassNotFoundException {MapImpl map = new MapImpl();map.readFileInfo();System.out.println(map.min());System.out.println(map.max());System.out.println(map.errorMsg());}
}
@Target({ElementType.FIELD})
//表示自定义注解可保留到运行时
@Retention(RetentionPolicy.RUNTIME)
//自定义注解,注解名字是Length
public @interface Length {// 允许的字符串长度最小值int min();// 的允许字符串长度最大值int max();// 自定义错误提示String errorMsg();
}

在这个类里边写识别字符串的操作。

public class MapImpl implements Length {@Overridepublic int min()  {
//        String min = this.readFile("min");
//        System.out.println("最小值为:"+min);
//        return Integer.valueOf(min) ;String minValue = this.getMethedValue(Thread.currentThread().getStackTrace()[1].getMethodName());return Integer.valueOf(minValue);}@Overridepublic int max() {
//        String max = this.readFile("max");
//        System.out.println("最大值为:"+max);
//        return Integer.valueOf(max) ;String maxValue = this.getMethedValue(Thread.currentThread().getStackTrace()[1].getMethodName());return Integer.valueOf(maxValue);}@Overridepublic String errorMsg() {
//        String errorMessage = this.readFile("errorMsg");
//        System.out.println("错误信息:"+  errorMessage);
//        return errorMessage;String errorMsgValue = this.getMethedValue(Thread.currentThread().getStackTrace()[1].getMethodName());return errorMsgValue;}@Overridepublic Class<? extends Annotation> annotationType() {return null;}boolean state=true;private String getMethedValue(String name){if (state==true){state=false;methedValue= this.readFileInfo();}if(name.equals("errorMsg")){System.out.println("错误信息:"+  methedValue.get(name));return methedValue.get(name);}else if(name.equals("min")){return methedValue.get(name);}else if(name.equals("max")){System.out.println("最大值为:"+methedValue.get(name));return methedValue.get(name);}return null;}Map<String,String> methedValue = new HashMap<>();public Map<String, String> readFileInfo()  {try{BufferedReader br=new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入要读取文件的路径");//E:\zy\TGB-zgy-2022\老师设计模式课相关资料必须留着\米老师设计模式课小例子\JAVAtest\customAnnotations\target\classes\LengthImpl1\Person.classString fileName=br.readLine();DataInputStream csanner = new DataInputStream(new FileInputStream(new File(fileName)));ClassFile classFile = new ClassFile(csanner);List<FieldInfo> fieldsList = classFile.getFields();for (FieldInfo field:fieldsList){for (AttributeInfo attributeInfo : field.getAttributes()) {System.out.println(attributeInfo);String annotationValue = attributeInfo.toString().replace("(", ",");String annotationValue1 = annotationValue.replace(")", ",");String[] fields = annotationValue1.split(",");for (int i = 1; i < fields.length; i++) {String[] fieldSplit = fields[i].split("=");methedValue.put(fieldSplit[0].trim(),fieldSplit[1].trim());System.out.println(methedValue);}}}}catch (Exception e){System.out.println("获取文件失败"+e);}return methedValue;}
}

实现效果:

了解元注解(注解使用的地方,时间范围,是否生成文档,是否被继承)
@Retention:
指定注解的保留策略。它决定注解在编译后是否被保留在class文件中以及在运行时可见性。常用的保留策略包括:

RetentionPolicy.SOURCE:注解仅在源代码级别保留,不包含在编译后的class文件中。
RetentionPolicy.CLASS:注解在编译时被保留,并包含在class文件中,但在运行时不可见。
RetentionPolicy.RUNTIME:注解在编译时被保留,并包含在class文件中,可以在运行时通过反射机制获取到。
@Target:
指定注解可以应用的目标元素类型。它规定了注解可以用于哪些程序元素,如类、方法、字段等。常用的目标元素类型包括:

ElementType.TYPE:注解应用于类、接口、枚举等类型。
ElementType.METHOD:注解应用于方法。
ElementType.FIELD:注解应用于字段(属性)。
ElementType.PARAMETER:注解应用于方法的参数。
@Documented:
指定注解是否包含在生成的API文档中。如果一个注解被标记为@Documented,那么当使用javadoc工具生成API文档时,注解会包含在文档中。

@Inherited:
指定注解是否可以被继承。如果一个注解被标记为@Inherited,那么它可以被继承,即当一个类继承自有该注解的父类时,子类也会继承该注解。

结果

注解的好处:
代码文档化:注解可以用于生成代码文档,通过添加注解来标记类、方法或字段的说明,使得开发者和其他人员能够更好地理解代码的意图和用法。

编译时检查:注解可以用于在编译时对代码进行检查,以确保代码的正确性或进行静态分析。例如,通过自定义注解来标记特定的代码结构,编译器可以根据注解执行额外的检查或生成警告信息。

运行时处理:注解可以在运行时被解析和处理,用于执行特定的逻辑或配置应用程序。例如,通过注解可以配置依赖注入框架,实现对象的自动注入;或者使用注解来定义路由映射,简化Web应用程序的开发。

测试和调试:注解可以用于标记测试用例或调试相关的信息,以便测试框架或调试器能够自动化执行相应的操作。例如,通过注解标记测试方法,测试框架可以识别并执行这些方法作为测试套件的一部分。


http://www.ppmy.cn/news/800102.html

相关文章

独家发布全能在线语言翻译工具QTranslate v6.8.0 汉化中文版

QTranslate v6.8.0汉化版由心语家园(www.xinyucn.cc)发布。是一个轻量级的免费电子词典&#xff0c;通过集成各大在线翻译引擎实现便捷的实时翻译。这款软件综合了5款在线翻译引擎&#xff0c;分别为谷歌翻译、微软翻译、Promet Mobile、SDL和雅虎翻译&#xff0c;输入一段文字…

语音翻译常用数据集

语音翻译常用数据集 Fisher and CALLHOME Spanish-English Speech Translation 【基本信息】 Fisher and CALLHOME Spanish-English Speech Translation数据集是由约翰霍普金斯大学开发的&#xff0c;包含英语参考翻译和语音识别器各种形式的输出&#xff0c;补充了LDC Fish…

中英文互译在线翻译-在线翻译软件

中英文互译在线翻译哪个软件好用&#xff0c;今天给大家分享一款免费好用的批量翻译器,汇集了世界上最好的几个翻译平台&#xff08;百度/谷歌/有道&#xff09;&#xff0c;为什么这么多人使用它&#xff1f;首先第一点翻译质量高&#xff0c;选择性多。第二点支持各种语言互译…

python怎样发音_python在线发音_python翻译

python的发音。怎么说python。听英语音频发音。了解更多。在英式免费创建并分享自己的单词列表和小测验&#xff01; &#xff08;一&#xff09;python的起源python&#xff08;发音类似“派森”&#xff09;这个英文单词的意思是“蟒蛇”或“巫师”。在我们文章讨论的 万能…

python发音翻译-python实现在线翻译

本文实例为大家分享了python实现在线翻译的具体代码,供大家参考,具体内容如下 具体效果请看图 代码: import urllib.request import urllib.parse import json def translation(): while 1: print("-"*30) n = input("请选择:1 翻译 2 退出 :"…

前端实现语音识别、语音翻译

前端实现语音识别、语音翻译 需求&#xff1a;用户说一段话&#xff0c;转译英文 一、录音 使用的是js-audio-recorder 另我这个里面有些东西是不需要的&#xff0c;因为我有个录音波浪图的功能&#xff0c;大家可忽略 let recorder new Recorder({sampleBits: 16, // 采样…

调用百度aip实现短语音翻译(附代码)

我的本意是想在Xilinx PYNQ上实现语音翻译&#xff0c;做一个类似翻译宝的应用&#xff0c;由于百度智能云目前仅支持安卓和IOS上的语音翻译&#xff0c;所以想要在嵌入式设备上实现该功能&#xff0c;就需要顺序调用短语音识别API和通用翻译API&#xff0c;下面记录使用方法。…

韩语在线翻译图片识别_在线翻译有道小程序

在线翻译小程序、在线翻译拍照、在线翻译词典、文字识别小程序、翻译软件、文字识别转换软件、 【拍照在线翻译】是一款实用的实时在线外语翻译神器,它可以帮我很快实现中英文在线翻译,不管是短语句还很是长语句,翻译的正确率都很高,可以彻底解放我的双手和大脑。而日且这么…