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文件为例)发布到外部环境,但我们并不想显式地让别人看到我们的源码,此时就需要对源码进行加密保…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
