15. Java反射和注解

Java —— 反射和注解

      • 1. 反射
      • 2. 注解

1. 反射

动态语言:变量的类型和属性可以在运行时动态确定,而不需要在编译时指定
常见动态语言:Python,JavaScript,Ruby,PHP,Perl;常见静态语言(C,C++,C#,Go,Java)
Java:Java并不算是严格意义上的动态语言,从反射角度来说属于半动态语言(能通过反射机制实现了部分动态编程的能力)
Java反射机制:Java编程语言提供的一种强大的特性,它允许程序在运行时动态地获取类的信息,并通过该信息操作类的成员变量、方法和构造函数

Java 的反射机制:在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法

Java反射常用API
Class 类:反射的核心类,可以获取类的属性,方法等信息
Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值
Method类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法
Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法
获取Class对象的3种方法
           调用某个对象的getClass()方法
             ❶ 类名 对象名 = new 类名();
             ❷ Class 类对象名 = 对象名.getClass();
           使用Class类中的forName()静态方法(安全且性能好)
             ❸ Class 类对象名 = Class.forName(“类的完全限定名”);
高版本Java创建:var 类对象名 = 类名(需要创建类对象的类).class;
        Class<类型(类名)> 类对象名 = 类名(需要创建类对象的类.class;

  • 对应类的常用方法
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  • 对应代码
package reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 反射机制*/public class TestDemo {public static void main(String[] args) throws NoSuchMethodException,InvocationTargetException, IllegalAccessException,InstantiationException, NoSuchFieldException {// 创建类对象var classes = Information.class;System.out.println("类名:" + classes.getSimpleName());// 根据类获取当前类的完全限定名String className = classes.getName();System.out.println("当前类的完全限定名:" + className);// 根据获取当前类的包名String packageName = classes.getPackageName();System.out.println("包名:" + packageName);// 根据类获取当前普通方法名List<String> list = new ArrayList<>();Method[] methods = classes.getMethods();for (Method method : methods) {list.add(method.getName());}System.out.println("public方法个数:" + list.size());System.out.println("public方法:" + list);// 获取构造器(无参构造器)Constructor<Information> constructor = classes.getConstructor();// 利用无参构造器创建实例Object obj = constructor.newInstance();// 获取指定的普通方法,带参数Method publicMethod = classes.getMethod("publicMethod", String.class, int.class);// 获取指定私有方法Method privateMethod = classes.getDeclaredMethod("privateMethod", String.class);System.out.println("获取指定私有方法:" + privateMethod);// 强行开启私有方法访问权限privateMethod.setAccessible(true);// 获取所有普通public属性Field[] fields = classes.getFields();System.out.println("普通属性:" + Arrays.toString(fields));// 获取所有属性Field[] declaredFields = classes.getDeclaredFields();System.out.println("所有属性:" + Arrays.toString(declaredFields));// 获取属性名for (Field field:declaredFields) {String name = field.getName();System.out.print(name + ", ");}System.out.println();// 访问单个私有属性Field name = classes.getDeclaredField("name");// 强行打开权限name.setAccessible(true);System.out.println("访问单个私有属性:名称:" + name.getName() + "   类型:" +name.getType() + "  权限修饰符(二进制位标识的修饰符信息):" + name.getModifiers());// 私有方法调用privateMethod.invoke(obj, "零零");// 方法调用publicMethod.invoke(obj, "夏鸥", 22);System.out.println("无参构造器创建的实例:" + obj);// 获取有参构造器Constructor<Information> constructors = classes.getConstructor(String.class, int.class, String.class);// 有参构造器创建实例Object object = constructors.newInstance("王菲", 20, "2020002");// 获取指定的普通方法Method classesMethod = classes.getMethod("publicMethod");// 方法调用classesMethod.invoke(object);System.out.println("有参构造器创建的实例:" + object);}
}class Information{private String name = "赫敏";private int age = 20;public String num = "2020001";public Information() {}public Information(String name, int age, String num) {this.name = name;this.age = age;this.num = num;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getNum() {return num;}public void setNum(String num) {this.num = num;}@Overridepublic String toString() {return "TestDemo{" +"name='" + name + '\'' +", age=" + age +", num='" + num + '\'' +'}';}private void privateMethod() {System.out.println(name + " 私有方法");}private void privateMethod(String name) {this.name = name;System.out.println(name + "  私有方法");}public void publicMethod() {System.out.println(name + " 普通方法");}public void publicMethod(String name, int age) {this.name = name;this.age = age;System.out.println(name + age + " 普通方法");}
}
  • 应用实例
package reflect;import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.net.URL;/*** 要求:实例化与当前类在统一和包中的所有类*/
public class Instantiations {public static void main(String[] args) throws ClassNotFoundException, URISyntaxException, NoSuchMethodException,InvocationTargetException, InstantiationException, IllegalAccessException {/* 1. 获取当前包中的所有类名 */// 获取包名String packageName = Instantiations.class.getPackageName();// 获取当前绝对路径资源  ".":表示当前路径URL path = Instantiations.class.getResource(".");// 获取路径下的所有文件File file = new File(path.toURI());// 将所需文件过滤存储到数组(所有类)File[] files = file.listFiles(f -> f.getName().endsWith(".class"));// 获取到for (File sub:files) {String name = sub.getName();// 获取类名String className = name.replace(".class", "");System.out.println("实例化类:" + packageName + "." + className);Class<?> classes = Class.forName(packageName + "." + className);// 通过无参构造器创建实例Object obj = classes.getConstructor().newInstance();System.out.println(obj);}}
}

2. 注解

注解:元数据 / 注解(注解Annotation是一个接口),一种提供程序中元素信息和数据的途径和方法
作用:在不改变程序主体逻辑的情况下,为程序员提供额外的元数据信息(标记一段代码的功能、作用范围、参数要求等信息)

4种标准元注解:元注解的作用是负责注解其他注解
       ❶ @Target 注解修饰范围 / 修饰的目标元素类型
       ❷ @Retention:注解生命周期 / 保留级别 / 被保留的时间长短
       ❸ @Documented注解是否会被包含在Java文档中生成
       ❹ @Inherited注解是否可以被继承
  @Target元素类型
       ElementType.TYPE:类、接口或枚举类型
       ElementType.FIELD:字段或属性
       ElementType.METHOD:方法
       ElementType.PARAMETER:方法参数
       ElementType.CONSTRUCTOR:构造函数
       ElementType.LOCAL_VARIABLE:局部变量
       ElementType.ANNOTATION_TYPE:注解类型
       ElementType.PACKAGE:包
  @Retention的三个值
       RetentionPolicy.SOURCE:注解仅存在于源代码中,编译时会被丢弃
       RetentionPolicy.CLASS:注解存在于源码和编译后的字节码文件中,但在运行时会被丢弃(默认值)
       RetentionPolicy.RUNTIME:注解在运行时保留在字节码文件中,可以通过反射机制读取
  @Documented和@Inherited
       一个注解被@Documented修饰,那么它的信息将会被包含在生成的文档中
       一个注解被@Inherited修饰,表示该注解可以被子类继承

  • 基本原则:不直接干扰程序代码的运行
    Java 注解是一种元数据,它可以提供对程序元素(如类、方法、字段等)的额外信息或配置,并且不会直接影响程序的运行逻辑,只是一种机制,用于存储和传递额外的信息
  • 注解分类
    在这里插入图片描述

  • 声明注解及变长参数

package reflect.annotations;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 AutoRunMethod {// 注解的参数(当注解下的参数只有一个时,一般用value)int value() default 1;String name() default "张三";
}
  • 使用注解
package reflect;import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.Arrays;public class Reflect {public static void main(String[] args) {// 加载包下被注解的类被注解的方法try {String packName = Reflect.class.getPackage().getName();File dir = new File(Reflect.class.getResource(".").toURI());File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));for (File sub:subs) {String className = sub.getName().replace(".class","");Class classes = Class.forName(packName + "." + className);if (classes.isAnnotationPresent(AutoRunClass.class)){System.out.println("实例化:" + className);Constructor constructor = classes.getConstructor();Object obj = constructor.newInstance();System.out.println(obj);// 方法名获取Method[] methods = classes.getDeclaredMethods();for (Method method:methods) {// 判断该方法是否被注解if (method.isAnnotationPresent(AutoRunMethod.class)){System.out.println("调用方法:" + method.getName() + "()");// 获取注解参数AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);// 获取值(定义时将其认为参数,调用时看作方法)int value = arm.value();String name = arm.name();System.out.println("注解参数的值:" + value + name);// 根据注解参数的值调用方法for (int i = 0; i < value; i++) {// 方法调用method.invoke(obj);}}}}}} catch (URISyntaxException | ClassNotFoundException |NoSuchMethodException | InstantiationException |IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}}
}// 注解类
@AutoRunClass
class Student {public String address = "贵阳市花溪区";private String name = "赵涛";private char gender = '男';private int age = 15;public Student() {}public Student(String name, char gender, int age) {this.name = name;this.gender = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 注解方法@AutoRunMethod(3)public void sayHi() {System.out.println(name + ":你好");}@AutoRunMethod(value = 2, name = "李四")public void sleep() {System.out.println(name + ":睡觉");}@AutoRunMethod(name = "王五")public void watchTV() {System.out.println(name + ":看电视");}public void playGame() {System.out.println(name + ":玩游戏");}public void say(String info) {System.out.println(name + "说:" + info);}public void say(String info, int count) {System.out.println(name + "说了" + count + "次," + info);}public void study() {System.out.println(name + "学习");}@AutoRunMethodpublic void doHomework() {System.out.println(name + ":做作业");}// **********************普通方法(参数变长)只是Java编译器认可(最终为数组)***************************// 变长参数只能在方的最后一个参数,且一个方法只能有一个变长参数public void doSome(String... s) {System.out.println("参数个数:" + s.length);System.out.println("参数:" + Arrays.toString(s));}private void privateMethod() {System.out.println("这是一个私有方法");}@Overridepublic String toString() {return "Student{" +"address='" + address + '\'' +", name='" + name + '\'' +", gender=" + gender +", age=" + age +'}';}
}
  • 变长参数只能在方的最后一个参数,且一个方法只能有一个变长参数
  • 注解格式:
          类型 参数名() [default 默认值] 注:不指定默认值时使用注解必须传递对应参数
  • 注解传参机制:
    当注解仅有一个参数,且参数名为value时,直接传入参数(不需要参数名)
    当注解仅有一个参数,且参数名不为value时,正常使用注解传参语法:参数名=参数值
    多个参数传参使用参数名进行传参,传参顺序可以与注解定义时参数顺序不一致
    有多个参数时,即使一个注解的参数名为value,在实际使用时参数名也不可以忽略

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/158031.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【云备份项目】

文章目录 [TOC](文章目录) 一、项目框架定义1.项目需求2. 服务端框架搭建思想3.客户端框架搭建思想 二、环境搭建1.gcc编译器升级2.安装第三方库 三、认识第三方库1.json库使用2.bundle库使用3.httplib库使用4.简单服务器搭建5.简单客户端搭建 四、文件使用工具类设计1.类的功能…

3. Windows下C++/MFC调用hiredis库操作redis示例

一、头文件目录 将之前下载和编译好的Redis目录拷贝到新建好的工程目录下面&#xff0c;再点击测试工程的右键/属性&#xff0c;点击C/常规&#xff0c;附加包含目录添加以下路径&#xff0c;注意如果原先有多个路径&#xff0c;在末尾处添加分号后再粘贴&#xff1a; 点击C/常…

树莓派玩转openwrt软路由:11.OpenWrt安装NodeRed

1、更新软件源 opkg update2、安装nodered docker run -it -p 1880:1880 --name mynodered nodered/node-red3、安装完整性测试 实现一个打印hello world的demo&#xff0c;每隔1秒打印一次

css 星星闪烁加载框

今天带来的是普灵普灵的loader闪烁加载框 效果如下 开源精神给我们带来了源码 ,源码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Spring framework Day10:JSR330注入注解

前言 JSR330是Java社区标准化进程&#xff08;Java Community Process&#xff0c;简称JCP&#xff09;中的一个规范&#xff0c;全名为"Dependency Injection for Java"&#xff0c;即Java的依赖注入规范。它定义了一组注解和相关的规范&#xff0c;用于实现依赖注…

python每日一练(7)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Visual Studio 错误CS0006:未能找到元数据文件踩坑记录

前言 在写项目的时候&#xff0c;添加了个新的Nuget包&#xff0c;突然就不行&#xff0c;然后就是报错&#xff0c;找不到文件、 出现的原因是因为项目之间互相引用出现了问题&#xff0c;比如如下情况 先版本回退 如果有Git仓库 第一时间去看Git 文件比较&#xff0c;找到…

YOLOv5算法改进(11)— 主干网络介绍(MobileNetV3、ShuffleNetV2和GhostNet)

前言:Hello大家好,我是小哥谈。主干网络通常指的是深度学习中的主干模型,通常由多个卷积层和池化层组成,用于提取输入数据的特征。在训练过程中,主干网络的参数会被不断优化以提高模型的准确性。YOLOv5算法中的主干网络可以有多种替换方案,为了后面讲解的方便,本篇文章就…

自动驾驶学习笔记(三)——场景设计

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 场景设计平台 场景地图 场景基本…

【NLTK系列01】:nltk库介绍

一、说明 NLTK是个啥&#xff1f;它是个复杂的应用库&#xff0c;可以实现基本预料库操作&#xff0c;比如&#xff0c;、将文章分词成独立token&#xff0c;等操作。从词统计、标记化、词干提取、词性标记&#xff0c;停用词收集&#xff0c;包括语义索引和依赖关系解析等。 …

Android---java线程优化 偏向锁、轻量级锁和重量级锁

java 中的线程是映射到操作系统原生线程之上的&#xff0c;如果要阻塞或唤醒一个线程就需要操作系统的帮忙&#xff0c;这就需要从用户态转换到核心态。状态转换需要花费很多时间&#xff0c;如下代码所示&#xff1a; private Object lock new Object();private int value;p…

异星工场入门笔记-01

两年前玩过一点&#xff0c;不看教程&#xff0c;单纯地开放世界自己探索&#xff0c;没有同类游戏经验&#xff0c;因此很难有获得感所以放弃了。现在正版游戏涨到130&#xff0c;看在逆势上涨的份上&#xff0c;我倒想继续探索下这个游戏的价值。 玩魔方&#xff0c;记教程步…

Kubernetes使用OkHttp客户端进行网络负载均衡

在一次内部Java服务审计中&#xff0c;我们发现一些请求没有在Kubernetes&#xff08;K8s&#xff09;网络上正确地实现负载均衡。导致我们深入研究的问题是HTTP 5xx错误率的急剧上升&#xff0c;由于CPU使用率非常高&#xff0c;垃圾收集事件的数量很多以及超时&#xff0c;但…

【UE 插件】UE4 虚幻引擎 插件开发(带源码插件打包、无源码插件打包) 有这一篇文章就够了!!!

目录 0 引言1 快速入门1.1 新建插件的前提1.2 创建插件步骤1.3 打包插件 2 无源代码的插件制作3 插件详细介绍3.1 插件的使用方法3.1 UE 预置插件模版3.1.1 空白3.1.2 纯内容3.1.3 编辑器独立窗口3.1.4 编辑器工具栏按钮3.1.5 编辑器模式3.1.6 第三方库3.1.7 蓝图库 3.2 插件中…

华为OD机试 - 最大括号深度 - 栈stack(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。 刷的越多,

本、硕、博区别真的辣么大吗?

61&#xff1a; 发际线已经说明了一切…… Super Mario&#xff1a; 小学&#xff0c;老师告诉学生&#xff1a;“森林里有只老虎&#xff0c;已经被我关在笼子里&#xff0c;我会带你去那个地方&#xff0c;然后给你一把猎枪&#xff0c;告诉你猎枪怎么用&#xff0c;并开枪…

搭建一个vscode+uni+vue的小程序项目

我们使用 vue2 创建工程作为示例&#xff0c;uni-app中Vue2版的组件库和插件也比较多&#xff0c;稳定、问题少&#xff0c;可以先参考下官方文档:uni-app官网 既然是使用vue脚手架&#xff0c;那肯定要全局安装vue/cli&#xff0c;已安装的可以跳过。 注意&#xff1a;Vue2创…

day05-前后端项目上传到gitee、后端多方式登录接口、发送短信功能、发送短信封装、短信验证码接口、短信登录接口

1 前后端项目上传到gitee 2 后端多方式登录接口 2.1 序列化类 2.2 视图类 2.3 路由 3 发送短信功能 4 发送短信封装 4.0 目录结构 4.1 settings.py 4.2 sms.py 5 短信验证码接口 6 短信登录接口 6.1 视图类 6.2 序列化类 1 前后端项目上传到gitee # 我们看到好多开源项目…

解决react使用css module无法重写bootstrap样式的问题

react使用css module虽然能够解决样式污染&#xff0c;但是同时也失去了写css样式的灵活性&#xff0c;特别是&#xff1a;在.module.css文件中当子元素是非变量的静态class类&#xff08;比如bootstrap&#xff09;, 此时使用css选择器对该子元素的样式不会起作用的 比如下面…

boot分页

List<ElectricDispatchTodoPO> todoList electricDispatchTodoService.queryTodlList(vo, sysStaffVO);// 计算总记录数int total todoList.size();// 如果总记录数大于0PageInfo<ElectricDispatchTodoPO> pageInfo new PageInfo<>();if (total > 0) {…