java反射:获取Class实例、创建运行时类对象、调用指定结构

news2024/11/20 2:03:26

1. 获取Class实例(运行时类)

public void test1() throws ClassNotFoundException {
        //1.调用运行时类的静态属性:class
        Class clazz1 = User.class;
        System.out.println(clazz1);

        //2. 调用运行时类的对象的getClass()
        User u1 = new User();
        Class clazz2 = u1.getClass();

        //3. 调用Class的静态方法forName(String className)
        String className = "com.hongshan.User"; //全类名
        Class clazz3 = Class.forName(className);

        System.out.println(clazz1 == clazz2);//true
        System.out.println(clazz1 == clazz3);//true

        //4. 使用类的加载器的方式 (了解)
        Class clazz4 = ClassLoader.getSystemClassLoader().loadClass("com.hongshan.User");
        System.out.println(clazz1 == clazz4);//true
    }

上述四种方式中,第三种调用Class静态方法forName获取Class实例,一般在框架中运用得比较多,因为这种方法是动态获取实例的,不需要在编译阶段就定好具体哪一个类。第四种方式和第三种雷同。

2. 通过运行时类创建对象

通过反射创建对象,是通过第一章节中获取的Class实例(运行时类)来创建对象的。在java8及之前通过运行时类创建对象推荐调用Class实例的newInstance()方法。此方法需要满足以下条件方可使用:
条件1:要求运行时类中必须提供一个空参的构造器
条件2:要求提供的空参的构造器的权限要足够。

    public void test1() throws InstantiationException, IllegalAccessException {

        Class clazz = Person.class;

        //创建Person类的实例
        Person per = (Person) clazz.newInstance();

        System.out.println(per);
    }
}

由于上述方式创建运行时类对象受限于两个条件,在java8之后,推荐使用Class实例获取构造器,通过构造器返回一个运行时类的实例对象。

public void test2() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Person.class;

        //1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
        Constructor constructor = clazz.getDeclaredConstructor();
        
        //2.setAccessible(true):确保此构造器是可以访问的
        constructor.setAccessible(true);
        
        //3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。
        Person person = (Person) constructor.newInstance();
        
        System.out.println(person);
    }

3. 通过运行时类调用指定结构

3.1 调用指定的属性

    public void test2() throws Exception {
        Class clazz = Person.class;

        //
        Person per = (Person) clazz.newInstance();

        //1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性
        Field nameField = clazz.getDeclaredField("name");

        //2. setAccessible(true):确保此属性是可以访问的
        nameField.setAccessible(true);

        //3. 通过Filed类的实例调用get(Object obj) (获取的操作)
        // 或 set(Object obj,Object value) (设置的操作)进行操作。
        nameField.set(per,"Tom");
        System.out.println(nameField.get(per));
    }

步骤1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性
步骤2. setAccessible(true):确保此属性是可以访问的
步骤3. 通过Filed类的实例调用get(Object obj) (获取的操作)或 set(Object obj,Object value) (设置的操作)进行操作。

3.2 调用指定的方法

  public void test3() throws Exception {
        Class clazz = Person.class;

        Person per = (Person) clazz.newInstance();

        //1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法
        Method showNationMethod = clazz.getDeclaredMethod("showNation",String.class,int.class);

        //2. setAccessible(true):确保此方法是可访问的
        showNationMethod.setAccessible(true);

        //3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。
        //invoke()的返回值即为Method对应的方法的返回值
        //特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null
        Object returnValue = showNationMethod.invoke(per,"CHN",10);
        System.out.println(returnValue);
    }

步骤1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法
步骤2. setAccessible(true):确保此方法是可访问的
步骤3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。
     invoke()的返回值即为Method对应的方法的返回值
     特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null

3.3 调用指定的构造器

public void test4() throws Exception {

        Class clazz = Person.class;

        //1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
        Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);

        //2.setAccessible(true):确保此构造器是可以访问的
        constructor.setAccessible(true);

        //3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。
        Person per = (Person) constructor.newInstance("Tom", 12);

        System.out.println(per);

    }

步骤1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
步骤2.setAccessible(true):确保此构造器是可以访问的
步骤3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。

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

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

相关文章

常见网络厂商设备默认用户名/密码大全

常见网络厂商的默认用户名/密码 01 思科 (Cisco) 设备类型:路由器、交换机、防火墙、无线控制器 默认用户名:cisco 默认密码:cisco 设备类型:网管型交换机 默认用户名:admin 默认密码:admin 02 华…

PH热榜 | 2024-11-18

DevNow 是一个精简的开源技术博客项目模版,支持 Vercel 一键部署,支持评论、搜索等功能,欢迎大家体验。 在线预览 1. Momen 标语:快速搭建你的最小可行产品,然后扩展它,无需任何编程经验。 介绍&#xff…

LoFTR: Detector-Free Local Feature Matching with Transformers—特征点匹配算法系列

LoFTR: Detector-Free Local Feature Matching with Transformers 受到:受到开创性作品 SuperGlue 的启发 摘要总结: 提出了一种局部图像特征匹配的新方法。更为突出说明的是室内场景下的特征点的匹配问题。 不是依次执行图像特征检测、描述和匹配&#…

Percona XtraBackup备份docker版本mysql 5.7

my.cnf配置文件 [client] default_character_setutf8[mysqld] # 数据存储目录(必须手动指定) datadir/var/lib/mysql/data# 字符集 collation_server utf8_general_ci character_set_server utf8 # 二进制日志 server-id1 log_bin/var/log/mysql/binl…

Windows安装vcpkg教程(VS2022)

内容摘要: 本文详细介绍如何在Windows系统上使用 Git 克隆 vcpkg 仓库来安装vcpkg工具,并链接Visual Studio 2022。 目录 一、关于vcpkg 二、开发环境 三、安装Git 四、使用 Git 克隆 vcpkg 仓库 一、关于vcpkg vcpkg 是一个开源的 C 包管理工具&am…

nodejs入门(1):nodejs的前后端分离

一、引言 我关注nodejs还是从前几年做了的一个电力大数据展示系统开始的,当然,我肯定是很多年的计算机基础的,万变不离其宗。 现在web网站都流行所谓的前后端结构,不知不觉我也开始受到这个影响,以前都是前端直接操作…

智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建

hello~这里是维小帮,如有项目需求和技术交流欢迎大家私聊我们!点击文章最下方获取智慧停车场方案~撒花! 随着城市化进程的加速,停车难问题日益凸显。智能停车系统作为缓解停车压力的有效手段,其核心技术与架构的构建至…

Django5 2024全栈开发指南(三):数据库模型与ORM操作

目录 一、模型的定义二、数据迁移三、数据表关系四、数据表操作4.1 Shell工具4.2 数据新增4.3 数据修改4.4 数据删除4.5 数据查询4.6 多表查询4.7 执行SQL语句4.8 数据库事务 Django 对各种数据库提供了很好的支持,包括 PostgreSQL、MySQL、SQLite 和 Oracle&#x…

中仕公考怎么样?事业编面试不去有影响吗?

事业编考试笔试已经通过,但是面试不去参加会有影响吗? 1. 自动放弃面试资格:未能按时出席事业单位的面试将被视为主动放弃该岗位的竞争机会。 2. 个人信誉问题:面试作为招聘流程的关键步骤,无故缺席可能被解释为诚信…

MySql结合element-plus pagination的分页查询

实现效果如下: 重点:使用mysql查询的limit和offset 原生SQL写法: select c.id as deptid,c.name as department,position,a.name staffname,2024-11 as shijian ,CASE WHEN b.shijian IS NULL THEN no ELSE yes END AS submit from fa_wecom…

学习笔记019——Ubuntu部署tomcat

1、下载Tomcat压缩包。本人下载的版本是:apache-tomcat-8.5.77.tar.gz 2、将压缩包上传到Ubuntu某个目录。 本人存放的目录是 /opt 目录下, 命令解压: ## 解压tomcat压缩包 tar -zxvf apache-tomcat-8.5.77.tar.gz 3、vim打开bin目录的setclasspath…

【JavaSE】(6)抽象类和接口

目录 一、抽象类 1、什么是抽象类 2、抽象类的特点 3、抽象类的作用 4、抽象类示例代码 二、接口 1、什么是接口 2、接口的书写建议 3、接口的特点 4、实现多个接口 5、接口能“忘记类型” 6、接口间的继承 7、接口的应用 7.1、引用类型的比较--Comparable 和 Co…

Git学习教程(更新中)

持续更新完善中… 1 Git简介 1.1 Git是什么? Git是一个开源的分布式版本控制系统,由Linus Torvalds创建,用于有效、高速地处理从小到大的项目版本管理。它能够记录项目文件的变更历史,让多个开发者可以协作开发同一个项目&#…

TON商城与Telegram App:生态融合与去中心化未来的精彩碰撞

随着区块链技术的快速发展,去中心化应用(DApp)逐渐成为了数字生态的重要组成部分。而Telegram作为全球领先的即时通讯应用,不仅仅满足于传统的社交功能,更在区块链领域大胆探索,推出了基于其去中心化网络的…

〔 MySQL 〕数据类型

目录 1.数据类型分类 2 数值类型 2.1 tinyint类型 2.2 bit类型 2.3 小数类型 2.3.1 float 2.3.2 decimal 3 字符串类型 3.1 char 3.2 varchar 3.3 char和varchar比较 4 日期和时间类型 5 enum和set mysql表中建立属性列: 列名称,类型在后 n…

两行命令搭建深度学习环境(Docker/torch2.5.1+cu118/命令行美化+插件),含完整的 Docker 安装步骤

深度学习环境的配置过于繁琐,所以我制作了两个基础的镜像,希望可以帮助大家节省时间,你可以选择其中一种进行安装,版本说明: base 版本基于 pytorch/pytorch:2.5.1-cuda11.8-cudnn9-devel,默认 python 版本…

免费实时图片编辑工具:MagicQuill

参看: https://huggingface.co/spaces/AI4Editing/MagicQuill 人工智能交互式图像编辑:可以制定涂改增加删除

前端学习八股资料CSS(五)

更多详情:爱米的前端小笔记,更多前端内容,等你来看!这些都是利用下班时间整理的,整理不易,大家多多👍💛➕🤔哦!你们的支持才是我不断更新的动力!找…

翼鸥教育:从OceanBase V3.1.4 到 V4.2.1,8套核心集群升级实践

引言:自2021年起,翼鸥教育便开始应用OceanBase社区版,两年间,先后部署了总计12套生产集群,其中核心集群占比超过四分之三,所承载的数据量已突破30TB。自2022年10月,OceanBase 社区发布了4.2.x 版…

如何在 Ubuntu 22.04 上安装 ownCloud

简介 ownCloud 是一个开源的个人云存储平台,它允许用户在本地服务器上存储和同步文件,提供了一个类似于 Dropbox 或 Google Drive 的服务,但是更加注重隐私和数据控制。以下是 ownCloud 的一些基础使用简介: 文件存储&#xff1…