day24_java的反射机制
反射
一、反射的概念
反射:加载类,反射出类的各个组成部分(类的成员:构造方法,属性,方法)
java反射机制:在运行状态中,对于任何一个类都能够知道这个类的所有属性和方法;对于任意一个对象,能够调用它的任意属性和方法;这种动态获取信息的方式就称为反射。
二、加载类???怎么加载
当程序要使用某个类时,如果这个类没有加载到内存中,则系统会通过加载,连接,初始化三个步骤来实现对这个类的初始化。
-
加载:
将class(字节码)文件读取到内存中,并为之创建一个Class对象
任何类被使用时都会被创建一个Class对象(注:一个类只有一个Class对象)
-
连接:
- 验证:是否有正确的内部结构,并和其它协调一致
- 准备:负责为类的静态成员分配内存,并设置默认初始化
- 解析:将类的二进制数据中的符号引用替换成直接引用
-
初始化:
该阶段主要是为类的类变量初始化值的,初始化有两种方式:
- 在声明类变量时,直接给变量赋值
- 在静态初始化块为类变量赋值
(一)类加载的时机
- 创建类的实例
- 访问类的静态成员或给静态变量赋值
- 调用类的吧静态方法
- 初始化某个类的子类
- java命令运行某个类(如:java HelloWorld)
- 使用反射的方法(将某个类加载到类加载区)强制创建某个类的Class对象
(二)类加载器
负责将class 文件加载到内存中,并为之创建一个Class对象,如果了解类加载器的机制,可以的更好的理解程序的运行
类加载器的组成:
-
根类加载器: bootstrap classLoader
也被称为引导类加载类,负责Java核心类的加载
比如: System, String 等,在 JDK 中的JRE 中 lib 中的 rt.jar文件中
-
扩展类加载器: extension classLoader
负责jre的扩展目录中的jar的加载
-
系统类加载器: System classLoader
负责在JVM启动时加载来自java命令的class文件
三、反射类的成员
(一)获取Class对象的方式
// 先创建了一个Person类
public class Person {private String name;int age;public String address;public Person() {}private Person(String name){this.name = name;}Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show(){System.out.println("show");}public void method(String s){System.out.println("method"+s);}public String getString(String s,String m){return s+"----"+m;}private void function(){System.out.println("function");}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +'}';}
}
// 获取Person类的Class对象
// 方法1:
Person person = new Person();
Class c = person.getClass();
// 方法2:
Class c2 = Person.class;
// 方法3:
Class c3 = Class.forName("com.gxa.demo1.Person");
// c=c2=c3:因为一个类的Class对象只有一个
注:在开发中我们常使用第三种方式去做反射,因为第三种传入的是个字符串而不是具体的类名,这样的话就可以把这个值方法配置文件中去,方便修改。
(二)获取类加载器
a: 得到类的Class对象
Class c = Class.forName("com.gxa.demo1.Person");
b: 获取类的加载器
ClassLoader classLoader = c.getClassLoader();
-
使用类加载器加载其它的文件
// 得到Class对象 Class c = Class.forName("com.gxa.demo1.Person"); // 获取类加载器对象 ClassLoader classLoader = c.getClassLoader(); // 类加载器加载其它文件(加入我的src目录下面有一个jdbc.properties文件) InputStream in = classLoader.getResourceAsStream("jdbc.properties");
注:如果找不到文件则会返回null给输入流
(三)反射类的构造方法
-
public Constructor<T> getConstructor(类<?>... parameterTypes)
:返回一个Constructor
对象,返回的是public修饰的构造方法;如果不写参数则返回无参的构造函数对象;如果构造方法不是公共的将会报异常:NoSuchMethodExceptionClass c = Class.forName("com.gxa.demo1.Person"); // 返回公共的无参构造,如果无参构造不是public修饰的将会报错 Constructor constructor = c.getConstructor(); System.out.println(constructor); // 有参数传入:传入的参数是数据类型类的Class对象;下面是获取一个参数为String类型的构造方法对象 Constructor constructor = c.getConstructor(String.class); System.out.println(constructor);
-
public Constructor<?>[] getConstructors()
:返回一个public修饰的构造方法的Constructor对象的数组Constructor[] constructors = c.getConstructors(); // 返回的构造方法都是public修饰的 System.out.println(constructors);
-
public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
:返回一个Constructor
对象,不传参数返回无参的构造方法(没有修饰符的限制),如果构造方法不存在将报异常:NoSuchMethodException// 获取无参的构造方法 Constructor declaredConstructor = c.getDeclaredConstructor(); System.out.println(declaredConstructor);
-
public Constructor<?>[] getDeclaredConstructors()
:返回所有构造方法的Constructor对象的数组// 获取所有方法 Constructor[] declaredConstructors = c.getDeclaredConstructors(); System.out.println(declaredConstructors);
1、通过Constructor对象创建实例
// 获取Class对象
Class c = Person.class;
// 获取Person类的无参构造
Constructor declaredConstructor = c.getDeclaredConstructor();
// 通过构造方法对象创建一个Person类的实例对象
Object obj = declaredConstructor.newInstance();
System.out.println(obj);
注:如果获取的构造方法对象是一个非私有的,那么将会报IllegalAccessException
异常;
解决方案:
在Constructor类里面有一个方法叫作:public void setAccessible(boolean flag)
的方法,将此对象的accessible
标志设置为指示的布尔值。 true
的值表示反射对象应该在使用时跳过java的语法检查。
// 获取Class对象
Class c = Person.class;
// 获取Person类的无参构造
Constructor declaredConstructor = c.getDeclaredConstructor();
// 设置constructor对象的访问权限
declaredConstructor.setAccessible(true);
// 通过构造方法对象创建一个Person类的实例对象
Object obj = declaredConstructor.newInstance();
System.out.println(obj);// 通过有参构造方法创建类的实例
Class c = Person.class;Constructor declaredConstructor = c.getDeclaredConstructor(String.class);declaredConstructor.setAccessible(true);Object obj = declaredConstructor.newInstance("张三");
System.out.println(obj);
(四)反射类的属性
与获取构造方法对象的获取方法相似:
-
public Field getField(String name)
:返回一个Field
对象,它反映此表示的类或接口的指定公共成员字段类对象。Class c = Person.class; Field addressField = c.getField("address"); System.out.println(addressField);
注:在使用getField方法是如果传的name为不存在的属性或非公共属性将会报异常:NoSuchFieldException
-
public Field[] getFields()
:返回包含一个数组Field
对象反射由此表示的类或接口的所有可访问的公共字段类对象。// 获取该类公共属性的field对象的数组 Field[] fields = c.getFields();
-
public Field getDeclaredField(String name)
:返回一个Field
对象,它反映此表示的类或接口的指定字段类对象。Field name = c.getDeclaredField("name");
-
public Field[] getDeclaredFields()
:返回的数组Field
对象反映此表示的类或接口声明的所有字段类对象。获取所有属性的field对象集合 Field[] fields = c.getDeclaredFields();
1、通过反射来给Person的对象赋值
// 没有对象就没有属性
// 要使用属性,必须 要有对象
// 1、反射一个无参的构造方法的Constructor对象
Constructor constructor = c.getDeclaredConstructor();
// 2、创建对应的对象
Object obj = constructor.newInstance();
// 3、反射Person类的属性对象
Field namefield = c.getDeclaredField("name");
Field agefield = c.getDeclaredField("age");
Field addressfield = c.getDeclaredField("address");
// 4、给对象实例赋值
namefield.setAccessible(true); // 设置私有属性的访问权限
namefield.set(obj,"张三");
agefield.set(obj,18);
addressfield.set(obj,"成都");
System.out.println(obj);
(五)反射类的方法
-
public 方法 getDeclaredMethod(String name,类<?>... parameterTypes)
:返回一个方法
对象,它反映此表示的类或接口的指定声明的方法类对象。 -
public 方法[] getDeclaredMethods()
:返回包含一个数组方法
对象反射的类或接口的所有声明的方法,通过此表示类
对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 -
public 方法 getMethod(String name,类<?>... parameterTypes)
:返回一个方法
对象,它反映此表示的类或接口的指定公共成员方法类
对象。 -
public 方法[] getMethods()
:返回包含一个数组方法
对象反射由此表示的类或接口的所有公共方法类
对象,包括那些由类或接口和那些从超类和超接口继承的声明。// 1、获取Class对象 Person person = new Person(); Class aClass = person.getClass(); // 2、获取Person的方法Method对象 Class对象.getDeclaredMethod("方法名",数据类型的Class对象); Method method = aClass.getDeclaredMethod("method", String.class); // invoke是Method类中的方法:表示调用某个具体对象的方法 Method对象.invoke(类的实例对象,参数...); // 通过Method对象调用person对象的method方法,为了防止权限不够(方法为私有的)最好使用setAccessible(true)来跳过java的代码检查 method.setAccessible(true); method.invoke(person,"反射调用了method方法");
案例:
在ArrayList 对象中添加一个字符串;
我们知道指定了ArrayList中参数的类型再传入其他类型的话java会报错,那么这个时候我们就可以通过反射的方式去获取ArrayList类中的add方法给ArrayList的对象赋值,因为ArrayList类的add方法传入的参数是一个泛型而不是具体的类型,所以我们可以添加任意数据:
// 1、创建一个ArrayList<Integer>对象 ArrayList<Integer> list = new ArrayList<>(); // 2、通过反射的方式获取ArrayList的Class对象 Class listClass = list.getClass(); // 3、通过Class对象反射add方法 Method listAdd = listClass.getDeclaredMethod("add",Object.class); // 4、通过ArrayList类的add方法给ArrayList<Integer>实例对象添加值// 4.1、为了防止访问的权限不够加上setAccessible方法跳过java代码检查 listAdd.setAccessible(true);// 4.2、添加值 listAdd.invoke(list,"我在Integer类型的集合里添加了一个字符串"); // 5、打印输出list集合 System.out.println(list);
面试题
面试题
第一题:JDBC操作数据库的步骤 ?
1)注册数据库驱动。
2)建立数据库连接。
3)获取statemen对象。
4)执行SQL语句。
5)返回结果(如果是查询操作有结果集:处理结果集)。
6)(释放资源)关闭数据库连接
第二题:JDBC中的Statement 和PreparedStatement,CallableStatement的区别?
1)PreparedStatement是预编译的SQL语句,效率高于Statement。
2)PreparedStatement支持“?”操作符,相对于Statement更加灵活。
3)PreparedStatement可以防止SQL注入,安全性高于Statement。
4)CallableStatement适用于执行存储过程。
第三题:execute,executeQuery,executeUpdate的区别是什么?
· Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpdateCount()方法来获取更新的记录条数。
· Statement的executeQuery(String query)接口用来执行select查询,并且返回ResultSet。即使查询不到记录返回的ResultSet也不会为null。我们通常使用executeQuery来执行查询语句,这样的话如果传进来的是insert或者update语句的话,它会抛出错误信息为 “executeQuery method can not be used for update”的java.util.SQLException。
· Statement的executeUpdate(String query)方法用来执行insert或者update/delete(DML)语句,或者 什么也不返回DDL语句。返回值是int类型,如果是DML语句的话,它就是更新的条数,如果是DDL的话,就返回0。
· 只有当你不确定是什么语句的时候才应该使用execute()方法,否则应该使用executeQuery或者executeUpdate方法。
第四题:PreparedStatement的缺点是什么,怎么解决这个问题?
PreparedStatement的一个缺点是,我们不能直接用它来执行in条件语句;需要执行IN条件语句的话,下面有一些解决方案:
1)分别进行单条查询——这样做性能很差,不推荐。
2)使用存储过程——这取决于数据库的实现,不是所有数据库都支持。
3)动态生成PreparedStatement——这是个好办法,但是不能享受PreparedStatement的缓存带来的好处了。
4)在PreparedStatement查询中使用NULL值——如果你知道输入变量的最大个数的话,这是个不错的办法,扩展一下还可以支持无限参数。
第五题:JDBC的ResultSet是什么?
在查询数据库后会返回一个ResultSet,它就像是查询结果集的一张数据表。
ResultSet对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了ResultSet的next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回false。可以在for循环中用它来遍历数据集。
默认的ResultSet是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的ResultSet。
当生成ResultSet的Statement对象要关闭或者重新执行或是获取下一个ResultSet的时候,ResultSet对象也会自动关闭。
可以通过ResultSet的getter方法,传入列名或者从1开始的序号来获取列数据。
相关文章:
day24_java的反射机制
反射 一、反射的概念 反射:加载类,反射出类的各个组成部分(类的成员:构造方法,属性,方法) java反射机制:在运行状态中,对于任何一个类都能够知道这个类的所有属性和方…...

VUE学习二、创建一个前端项目
1.创建一个vue项目 使用命令 vue ui启动vue脚手架 vue ui 等待项目创建好 可以来任务栏启动项目 参数那里可以设置启动端口等参数 启动成功 成功访问 2. 用webstorm 打开项目 脚手架页面可安装基本依赖 比如路由 使用ws打开项目 启动项目 npm run serve 3.修改启动…...

「红队笔记」靶机精讲:Prime1 - 信息收集和分析能力的试炼
「红队笔记」靶机精讲:Prime1 - 信息收集和分析能力的试炼 本文是作者在观看 B 站《红队笔记》后做的一些笔记及相关知识的补充。学渗透特别推荐大家去看。如有侵权,请联系作者,作者看到后会第一时间删除。 靶机精讲之Prime1,vu…...

JVM虚拟机系统性学习-对象的创建流程及对象的访问定位
对象的创建流程与内存分配 对象创建流程如下: Java 中新创建的对象如何分配空间呢? new 的对象先放 Eden 区(如果是大对象,直接放入老年代)当 Eden 区满了之后,程序还需要创建对象,则垃圾回收…...
perf与火焰图-性能分析工具
参考链接 perf性能分析工具使用分享 如何读懂火焰图?-阮一峰 perf基本用法-record,report-知乎 火焰图抓取 准备: centos安装perf工具 dnf install perf下载火焰图解析代码 git clone https://github.com/brendangregg/FlameGraph.git抓取指定进程…...

UniGui使用CSSUniTreeMenu滚动条
有些人反应UniTreeMenu当菜单项目比较多的时候会超出但是没有出滚动条,只需要添加如下CSS 老规矩,unitreemeu的layout的componentcls里添加bbtreemenu,然后在css里添加 .bbtreemenu .x-box-item{ overflow-y: auto; } 然后当内容超出后就会…...
Spring框架中的五种常用设计模式
1、单例模式 Spring 的 Bean 默认是单例模式,通过 Spring 容器管理 Bean 的⽣命周期,保证每个 Bean 只被 创建⼀次,并在整个应⽤程序中重用。 2.工厂模式 Spring 使⽤⼯⼚模式通过 BeanFactory 和 ApplicationContext 创建并管理 Bean 对象…...
华纳云:docker启动报错的原因和解决方法
Docker 启动报错可能由多种原因引起。以下是一些建议,可用于解决 Docker 启动问题: 查看 Docker 日志: 查看 Docker 的日志可以提供更多的详细信息,有助于定位问题。 sudo journalctl -xe | grep docker 或者查看 Docker 服务的详…...
代码规范及开发工具
代码规范及开发工具: 前端(vscode、idea): JavaScript规范: 1. 谷歌开源项目风格指南:JavaScript 、TypeScript篇 https://zh-google-styleguide.readthedocs.io/en/latest/google-typescript-…...

证件照制作小程序源代码
17638103951(同v)...

自治调优!人大金仓解放DBA双手
数据库系统的性能是确保整个应用系统高效运转的关键因素,因此数据库性能调优工作至关重要。KingbaseES通过将人工调优过程内化为数据库内核,成功实现了自治调优。这种创新的调优方案为DBA提供了更高效且准确的性能调优途径,同时也显著降低了数…...

深度学习环境配置------windows系统(GPU)------Pytorch
深度学习环境配置------windows系统(GPU)------Pytorch 准备工作明确操作系统明确显卡系列 CUDA和Cudnn下载与安装1.下载2.安装 环境配置过程1.安装Anacoda2.配置环境1)创建一个新的虚拟环境2)pytorch相关库的安装 2.安装VScode1&…...

el-menu标题过长显示不全问题处理
项目基于vue-element-admin 问题 期望 处理方式 \src\layout\components\Sidebar\index.vue 文件后添加CSS <style scped> /* 侧栏导航菜单经典 文字超长溢出问题 CSS折行 */ .el-submenu__title {display: flex;align-items: center; } .el-submenu__title span {white-…...

微信游戏开发:连接社交与娱乐的创新之路
在移动互联网时代,微信已经成为了人们日常生活中不可或缺的社交工具。而微信游戏,作为在这一平台上崛起的新兴产业,不仅给用户提供了更多娱乐选择,也为开发者们创造了独特的机遇。本文将探讨微信游戏开发的关键步骤、技术要点以及…...

1688一件采购实现指南:含代码实现采购流程
一、引言 1688是中国最大的B2B电子商务平台之一,提供了丰富的商品信息和采购服务。一键采购是1688平台的一项便捷功能,可以帮助用户快速完成采购流程,提高采购效率。本文将详细介绍如何使用1688一键采购功能,并通过代码示例演示如…...

div中一个图片怎么铺满整个div而且不超出div按比例铺满div
重要信息: background-size:cover或者background-size:contain;属性 设置图片不重复: background-repeat:no-repeat; 设置字体在div中间:...

云原生之深入解析Kubernetes的架构及特性
一、kubernetes 架构 从宏观上来看 kubernetes 的整体架构,包括 Master、Node 以及 Etcd。Master 即主节点,负责控制整个 kubernetes 集群,它包括 Api Server、Scheduler、Controller 等组成部分。它们都需要和 Etcd 进行交互以存储数据&…...
分布工具类的定义与实现及测试。
package d5.util;public class PageUtil {private int pageSize;//一页有多少条private int currIndex;//当前是第几页private int totalCount;//共有多少条记录 谁给我? 逻辑层的 getTotalCountprivate int totalPage;//共有多少页 private int start;//显时时开始…...

如何在忘记密码的情况下恢复解锁 iPhone
您忘记了 iPhone 密码吗?Apple 官方通常建议将 iPhone 恢复至出厂设置以将其删除。这种修复很不方便,甚至可能比问题本身更麻烦。 如果您也经历过同样的情况,并且想知道忘记了 iPhone 密码并且不想恢复它该怎么办,我们的终极指南…...
通过compileall库将python文件编译为pyc文件
文章目录 什么是 .pyc 文件将 .py 文件编译为 .pyc 文件编译单个文件编译多个文件 在实际开发中,有时候需要将产品(以.py文件为例)发布到外部环境,但我们并不想显式地让别人看到我们的源码,此时就需要对源码进行加密保…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...