JavaSE之反射

news2024/9/22 17:28:54

目录

  • Class类
  • 反射的概念
    • 反射的好处
    • 反射的应用场景
  • 三种获取Class对象的方式
    • Class类中的方法
      • Class中获取构造器的方法
      • 获取成员方法对象
      • 获取成员变量
  • 反射案例
  • 最后

Class类

Class类创建的对象我们称为Class对象/类对象/字节码对象

Class对象会保存类中的信息(构造方法, 成员方法, 成员变量等)
有了Class对象就能得到类中的所有信息。

反射的概念

在程序的运行过程中, 通过Class对象得到类中的信息(构造方法, 成员方法, 成员变量), 并操作他们

这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。非正常的手段操作对象。

反射的好处

使用反射创建对象,代码更复杂,无视修饰符,
功能更强大灵活

反射的应用场景

IDEA的智能提示
框架Spring/SpringMVC/Mybatis

三种获取Class对象的方式

类名.class

对象.getClass()

Class.forName(“类全名”);

注意:三种方式获取到的是同一个Class对象

public static void main(String[] args) throws ClassNotFoundException {
        // 类名.class    Class<Employee>:
        Class<Employee> cls1 = Employee.class;
        System.out.println(cls1);
        // 对象.getClass()    Class<? extends Employee>:
        Employee employee = new Employee();
        Class<? extends Employee> cls2 = employee.getClass();
        System.out.println(cls2);
        // Class.forName("类全名"); 包名.类名  第三种使用最灵活(常用),因为类不存在也能通过编译
        Class<?> cls3 = Class.forName("com.itheima.bean.Employee");
        System.out.println(cls3);
    }

Class类中的方法

String getSimpleName(); 获得类名字符串:类名

String getName(); 获得类全名:包名.类名

public static void main(String[] args) {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到类中的信息
        String name = cls.getName();
        System.out.println(name);
        String simpleName = cls.getSimpleName();
        System.out.println(simpleName);
    }

Class中获取构造器的方法

getConstructors()

getConstructor (Class<?>… parameterTypes)

getDeclaredConstructors()

getDeclaredConstructor (Class<?>… parameterTypes)

反射得到的构造器可以做什么?

创建对象

public newInstance(Object… initargs)

如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
setAccessible(boolean)

反射可以破坏封装性,私有的也可以执行了。

public class Demo06 {
    // 得到所有public的构造器: getConstructors
    @Test
    public void test01() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到所有public的构造器
        Constructor<?>[] constructors = cls.getConstructors();
        for (Constructor o:constructors){
            System.out.println(o);
        }
    }

    // 得到一个public的构造器: getConstructor
    @Test
    public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到一个public的构造器
        Constructor<Employee> constructor = cls.getConstructor();
        System.out.println(constructor);
        Constructor<Employee> constructor1 = cls.getConstructor(String.class, int.class);
        System.out.println(constructor1);
        // Constructor<Employee> c = cls.getConstructor(); // 匹配无参 public Employee()

        // 3.使用构造器创建对象
        Employee employee = constructor.newInstance();
        Employee employee1 = constructor1.newInstance("张三", 88);
        System.out.println(employee);
        System.out.println(employee1);

    }

    // 得到所有存在的构造器: getDeclaredConstructors
    @Test
    public void test03() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到所有存在的构造器     Declared:声明的,存在的
        //包括私有,protected等
        Constructor<?>[] constructors = cls.getDeclaredConstructors();
        for (Constructor o : constructors){
            System.out.println(o);
        }
    }

    // 得到一个存在的构造器: getDeclaredConstructor
    @Test
    public void test04() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到一个存在的构造器
        Constructor<Employee> constructor = cls.getDeclaredConstructor();
        Constructor<Employee> constructor1 = cls.getDeclaredConstructor(String.class);
        // 3.使用构造器创建对象
        Employee employee = constructor.newInstance();
        constructor1.setAccessible(true);
        Employee employee1 = constructor1.newInstance("王五");
        System.out.println(employee);
        System.out.println(employee1);
    }
}

获取成员方法对象

Class中获取成员方法的方法

getMethods()

getMethod(String name, Class<?>… parameterTypes)

getDeclaredMethods()

getDeclaredMethod (String name, Class<?>… parameterTypes)

反射得到成员方法可以做什么?

依然是在某个对象中触发该方法执行。

Object invoke​(Object obj, Object… args)

如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
setAccessible(boolean)

public class Demo07 {
    // 得到所有public的方法: getMethods
    @Test
    public void test01() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到所有public的方法
        Method[] methods = cls.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
    }

    @Test
    // 得到所有存在的方法: getDeclaredMethods

    public void test02() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到所有存在的方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
    }

    // 得到一个public的方法: getMethod
    @Test
    public void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到一个public的方法
        Method setName = cls.getMethod("setName", String.class);
        // 3.调用方法
        // Object invoke(Object obj, Object... args)
        Employee instance = cls.getConstructor().newInstance();
        instance.setAge(19);
        setName.invoke(instance, "李四");

        Method getName = cls.getMethod("getName");
        Object invoke = getName.invoke(instance);
        System.out.println(invoke);
        // Object obj: 调用方法的对象
        // Object... args: 方法的参数
        // Object: 返回值

    }

    // 得到一个存在的方法: getDeclaredMethod
    @Test
    public void test04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1.得到Class对象
        Class<?> cls = Class.forName("com.itheima.bean.Employee");
        // 2.得到一个存在的方法
        Method sleep = cls.getDeclaredMethod("sleep", int.class);
        // 3.调用方法
        Object instance = cls.getConstructor().newInstance();
        sleep.setAccessible(true);
        Object hours = sleep.invoke(instance, 2);
        System.out.println(hours);
    }
}

获取成员变量

获取类中成员变量对象的方法

getFields()

getField(String name)

getDeclaredFields()

getDeclaredField(String name)

反射得到成员变量可以做什么?(不常用,因为我们一般通过方法来取值赋值,这样直接拿成员变量赋值效率低)

依然是在某个对象中取值和赋值。

void set​(Object obj, Object value):

Object get​(Object obj)

如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
setAccessible(boolean)

public class Demo08 {
    // 得到所有public的成员变量: getFields
    @Test
    public void test01() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;
        // 2.得到所有public的成员变量
        Field[] fields = cls.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
    }

    // 得到所有存在的成员变量: getDeclaredFields
    @Test
    public void test02() {
        // 1.得到Class对象
        Class<Employee> cls = Employee.class;

        // 2.得到所有存在的成员变量
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println(f);
        }
    }

    // 得到一个public的成员变量: getField
    @Test
    public void test03() throws NoSuchFieldException {
        // 1.得到Class对象
        Class<Employee> employeeClass = Employee.class;
        // 2.得到Field
        Field weight = employeeClass.getField("weight");
        System.out.println(weight);
    }

    // 得到一个存在的成员变量: getDeclaredField
    @Test
    public void test04() throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1.得到Class对象
        Class<Employee> employeeClass = Employee.class;
        // 2.得到Field
        Field age = employeeClass.getDeclaredField("age");
        // 3.给成员变量赋值
        // set(Object obj, Object value);
        Employee employee = employeeClass.getConstructor().newInstance();
        age.setAccessible(true);
        age.set(employee, 99);
        // Object obj: 成员变量所在对象
        // Object value: 新的值

        // 4.获取成员变量的值

        Object o = age.get(employee);
        System.out.println(o);
        // Object get(Object obj);
        // Object obj: 成员变量所在对象
        // Object: 返回成员变量的值
    }
}

反射案例

需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。
分析:

通过Properties加载配置文件

得到类名和方法名

通过类名反射得到Class对象

通过Class对象创建一个对象

通过Class对象得到方法

调用方法

public class Demo09 {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileReader("D:\\it_workspace\\src\\config.properties"));
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        Class<?> cls = Class.forName(className);
        Object instance = cls.getConstructor().newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(instance);
    }
}

在这里插入图片描述

Teacher
在这里插入图片描述

最后

如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32CubeMX新建工程并点亮一个LED

可提前看&#xff1a;STM32CubeMX环境安装&#xff08;保姆级&#xff09; 目录 进入STM32CubeMX界面 双击软件&#xff0c;可能会出现的弹窗 更改固件路径 新建工程 进入配置环境 以一个点灯程序为例 GPIO配置 输出电平设置 输出模式 上下拉 输出速度 ​编辑 U…

【笑小枫的SpringBoot系列】【十六】SpringBoot生成PDF

关于笑小枫&#x1f495; Hello&#xff0c;我是笑小枫&#xff0c;欢迎来到我的世界&#xff0c;喜欢的朋友关注一下我呦&#xff0c;大伙的支持&#xff0c;就是我坚持写下去的动力。 笑小枫个人博客&#xff1a;https://www.xiaoxiaofeng.com 本文源码&#xff1a;https://g…

DVWA之SQL注入(盲注)

文章目录方法一&#xff1a;基于布尔盲注1.判断是否存在注入&#xff0c;注入类型2.猜数据库名3.猜解数据库中的表名4.猜列名5.猜表中的字段值方法二&#xff1a;基于时间盲注1.判断是否存在注入&#xff0c;注入是字符型还是数字型2.猜解当前数据库名3.猜解数据库中的表名4.猜…

ASPNetZero 11.4 Release Angular + MVC + Crack

Asp. NET 带有现代UI和稳定的结构&#xff0c;是新的网页应用的起点。它会提供预建和工作页以及很强的基本构造。 基础解决方案 你的下一个网络应用程序 ASP.NET Zero 是具有现代 UI 和 SOLID 架构以及完整源代码的新 Web 应用程序的起点。 ASP.NET Zero的好处 ASP.NET Zero 通…

化合物应用-动物给药方式

给药方式 针对实验动物的给药方式有很多种&#xff0c;总体可分为局部给药和系统给药。系统给药又可分为肠外给药和肠内给药。 1.1 肠内给药&#xff08;Enteral administration&#xff09; 口服&#xff08;per os&#xff0c;p.o&#xff09;给药由于具有经济、方便、安全…

虚拟形象sdk哪个好?可以快速制作专属元宇宙形象

元宇宙的火爆&#xff0c;催生了很多提供元宇宙基座的服务商&#xff0c;目前市面上提供虚拟形象SDK的服务商不少于20家&#xff0c;这里小编给大家推荐ZEGO即构科技的Avatar虚拟形象SDK。 即构Avatar虚拟形象SDK概述 即构Avatar支持自定义管理人物的虚拟形象&#xff0c;通过默…

【虹科新品】 HK-MR430330绝对式光纤编码器(上)

虹科MR430&330系列绝对式光纤编码器是用于确定轴位置的角度计&#xff0c;均为纯光学无源设计。HK-MR330系列适用于间隔距离较大的编码器和控制器&#xff0c;HK-MR430 系列适用于由于体积小而提供小空间的系统。与增量式旋转编码器相比&#xff0c;测量值在开启后立即可用…

【JAVA程序设计】基于SSM的图书管理系统-有论文文档

基于SSM的图书管理系统-有文档项目获取项目简介开发环境项目技术功能结构文档目录运行截图项目获取 获取方式&#xff08;点击下载&#xff09;&#xff1a;是云猿实战 项目经过多人测试运行&#xff0c;可以确保100%成功运行。 项目简介 这是一个基于ssm的图书管理系统&…

canvas绘制时钟

这篇文章用于介绍html5的新标签&#xff0c;<canvas></canvas> Canvas介绍 canvas是HTML5新增的元素&#xff0c;通过javascript脚本绘制图形。那么canvas可以用来干啥呢&#xff1f; 制作web网页游戏数据可视化&#xff1b;即&#xff1a;echarts就是基于canva…

ajax 学习记录

ajax 学习记录ecplise 下载安装创建项目创建ajax后台请求处理类新建包创建servletAjaxServlet 内容web.xml新建index.htmlindex.html内容运行ecplise 下载安装 ecplise 21.06 Eclipse IDE for Enterprise Java and Web Developers 下载 下载完直接解压运行 创建项目 先下载…

基于最小二乘支持向量机(LS-SVM)进行分类、函数估计、时间序列预测和无监督学习附Matlab代码

​✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法…

线性回归(机器学习)

用神经网络的思维来看待线性回归 单层的神经网络&#xff0c;其实就是一个神经元&#xff0c;可以完成一些线性的工作&#xff0c;比如拟合一条直线&#xff0c;这用一个神经元就可以实现。 当变量多于一个时&#xff0c;两个变量的量和数值有可能差别很大&#xff0c;这种情况…

MicroApp的Vite项目,特别全面

目录 前言 简介 分离 修改基座 子应用修改 修改vite.config.js​编辑 修改index.html 基座修改 处理子应用静态资源 效果 基座与子应用传值 在基座的MicroApp的index页面修改 在子应用的App.tsx文件进行useEffect的监听 效果​编辑 去掉菜单栏头部 效果​编辑 …

SpringBoot面试

0. Spring Boot 原理 Spring Boot 是由 Pivotal 团队提供的全新框架&#xff0c;其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。通过这种方式&#xff0c;Spring Boot 致力…

D. Bandit in a City(DFS + 叶子节点数目)

Problem - 1436D - Codeforces 输出标准输出 城市里出现了强盗! 他们中的一个正试图尽可能多地抓捕市民。 这个城市由n个广场组成&#xff0c;由n-1条道路连接&#xff0c;从任何其他广场都可以到达任何广场。1号广场是主广场。 星期天散步后&#xff0c;所有的道路都改为单行…

uni-app —— 小程序登录功能的相关实现

文章目录 前言一、示例图二、静态页面的搭建 1.登录页面的静态页面css样式设置2.我的页面的静态页面css样式设置三、登录页面的实现逻辑 1.进行表单验证的组件2.验证登录成功的思路3.具体代码实现一、示例图 二、静态页面的搭建 实现思路&#xff1a; 主要需要实现的功能点&am…

企业为什么做不好生产计划?

生产计划是企业对生产任务作出统筹安排&#xff0c;具体拟定生产产品的品种、数量、质量和进度的计划。是企业经营计划的重要组成部分&#xff0c;是企业进行生产管理的重要依据。既是实现企业经营目标的重要手段&#xff0c;也是组织和指导企业生产活动有计划进行的依据。企业…

【微服务】SpringCloud微服务注册源码解析

目录 一、前言 1、简述 2、SpringCloudCommons 项目 二、客户端服务注册 1、流程图 2、入口 2.1、客户端注册引入依赖 3、EurekaServiceRegistry服务注册机 3.1、EurekaServiceRegistry注册逻辑 4、ApplicationInfoManager 4.1、setInstanceStatus(InstanceStatus s…

【区块链技术与应用】(七)

资料来源 https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go#section-readme https://github.com/hyperledger/fabric-sdk-go https://wiki.hyperledger.org/display/fabric https://github.com/hyperledger/fabric-samples 书接上回&#xff0c;补充getway链码分析 上…

maven assembly打包生成Java应用启动脚本bat和sh

1. maven插件介绍 springboot应用通过maven插件appassembler-maven-plugi生成启动脚本bat和sh。根据官网介绍&#xff0c;这个插件主要用于生成启动 java应用程序的脚本&#xff0c;能将项目依赖jar能够打包目录中&#xff0c;并且它们加入启动脚本类路径中。 主要命令 appas…