MyBatis中将结果集封装到指定类型详解(反射Class.forName详解)

2024-01-11 05:08

本文主要是介绍MyBatis中将结果集封装到指定类型详解(反射Class.forName详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1.将结果集封装到指定类型中
      • 1.1指定类型:
      • 1.2将信息存入到mapper中
      • 1.3反射
        • 1.3.1获取全限定类名,加载类并且实例化
        • 1.3.2执行SQL语句,生成的结果集获取元信息,把每列的数据存入到指定类型中
  • 1.4Class.forName方法扩展
    • 理解 Class.forName()
    • Class.forName() 与 xxx.class的区别
        • 小结:
          • 初始化和实例化的区别:

1.将结果集封装到指定类型中

1.1指定类型:

1.2将信息存入到mapper中

mapper的构造:成员变量:``

private String queryString;//SQL    select * from user
private String resultType;//实体类的全限定类名 com.domain.User

1.3反射

1.3.1获取全限定类名,加载类并且实例化

object obj = Class.forName(mapper.getResultType())newInstance();//加载参数指定的类到内存

1.3.2执行SQL语句,生成的结果集获取元信息,把每列的数据存入到指定类型中

1.4Class.forName方法扩展

理解 Class.forName()

Class 类概念

Class 也是一个 Java 类,保存的是与之对应 Java 类的 meta信息(元信息),用来描述这个类的结构,比如描述一个类有哪些成员,有哪些方法等,一般在反射中使用。

**详细解释:**Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例(Class 对象)。也就是说,在 Java 中,每个 java 类都有一个相应的 Class 对象,用于表示这个 java 类的类型信息。

类加载概念

当使用一个类的时候(比如 new 一个类的实例),会检查此类是否被加载到内存,如果没有,则会执行加载操作。

读取类对应的 class 文件数据,解析此数据,构造一个此类对应的 Class 类的实例。此时JVM就可以使用该类了,比如实例化此类,或者调用此类的静态方法。

Java 也提供了手动加载类的接口,class.forName()方法就是其中之一。(说来说去,其实就是生成这个类的 Class)

类加载器的概念

顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance() 方法就可以创建出该类的一个对象。 基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例。

类初始化概念

类被加载之后,jvm 已经获得了一个描述类结构的 Class 实例。但是还需要进行类初始化操作之后才能正常使用此类,类初始化操作就是执行一遍类的静态语句,包括静态变量的声明还有静态代码块

Class.forName() 方法

此方法含义是:加载参数指定的类,并且初始化它

在 jdbc 连接数据库中的应用

到这里,不用解释,读者也会明白,在使用 jdbc 方式连接数据库时,为什么要执行 Class.forName(‘驱动类名’) 方法了:将驱动类的 class 文件装载到内存中,并且形成一个描述此驱动类结构的 Class 类实例,并且初始化此驱动类,这样 jvm 就可以使用它了,这就是 Class.forName() 方法的含义。

有数据库开发经验朋友会发现,为什么在我们加载数据库驱动包的时候有的却没有调用 newInstance() 方法呢?即有的 jdbc 连接数据库的写法里是 Class.forName(xxx.xx.xx);而有一 些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?

刚才提到,Class.forName(" "); 的作用是要求 JVM 查找并加载指定的类,如果在类中有静态初始化器的话,JVM 必然会执行该类的静态代码 段。而在 JDBC 规范中明确要求这个 Driver 类必须向 DriverManager 注册自己,即任何一个 JDBC Driver 的 Driver 类的代码都必须类似如下:

public class MyJDBCDriver implements Driver { static { DriverManager.registerDriver(new MyJDBCDriver()); } 
} 

既然在静态初始化器的中已经进行了注册,所以我们在使用 JDBC 时只需要 Class.forName(XXX.XXX); 就可以了。

Class.forName() 与 xxx.class的区别

所有的类都是在对其第一次使用时,动态加载到 JVM。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这也证明了构造器也是类的静态方法,即使在构造器之前并没有 static 关键字。因此,使用 new 操作符创建类的对象也会被当作对类的静态成员的引用。

因此 Java 程序在他开始运行之前并非被完全加载,其各个部分是在需要时才加载的。

类加载器首先槛车这个类的 Class 对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名称查找 .class 文件。在这个类的字节码被加载时,它们会接收验证,以确保其没有被破坏。

Class 对象尽在需要的时候才被加载。static 初始化是在类加载时进行的

对于 Class.forName(),这个方法是 Class 类的一个 static 成员。Class 对象就和其他对象一样,我们可以获取并操作他的引用。forName() 是取得 Class 对象引用的一种方法。他是用一个包含目标类的文本名的 String 作为输入参数,返回一个 Class 对象的引用。forName() 方法发现某个累还没被加载,就会主动去加载这个类,在加载过程中,该类的是 static 子句将会被执行。

Java 还提供了另一种方法来生成对 Class 对象的引用,即使用类字面常量。形如:xxx.class 的形式。但是这种形式创建 Class 对象引用时,不会自动初始化 Class 对象。初始化被延迟到了对静态方法或者非常数静态域首次引用时才执行。

从对 initable 引用的创建中可以看到,仅使用 .class 语法来获取对类的引用不会发生初始化。但是 Class.forName() 立即就进行了初始化。如果一个 static final 值是“编译期常量”,就像 Initable.staticFinal 那样,那么这个值不需要对 Initable 类进行初始化就可以被读取。但是如果只是将一个域设置为 static 和 final 的,还不足以确保这种行为,例如 Initable.staticFianl2 的访问将强制进行类型的初始化,因为他不是一个编译器常量。

小结:

Class.forName(“ ”) 加载参数到内存,返回一个class(类)对象,并且初始化该类

初始化和实例化的区别:

初始化时机:进入main方法前先会加载jdk基础类和main方法所在的类

​ 其他的类只有被使用到的时候才会被加载

实例化的方式:由执行类实例创建表达式而引起的对象创建(new)。除此之外,我们还可以使用反射机制(Class类的newInstance方法、使用Constructor类的newInstance方法)、使用Clone方法、使用反序列化等方式创建对象

初始化:类加载进来的时候就会对其初始化,静态变量(类加载器),静态代码块,构造器都会加入进内存

e方法、使用Constructor类的newInstance方法)、使用Clone方法、使用反序列化等方式创建对象

初始化:类加载进来的时候就会对其初始化,静态变量(类加载器),静态代码块,构造器都会加入进内存

实例化;一般是先对其初始化再实例化,将类的所有信息加载进内存

这篇关于MyBatis中将结果集封装到指定类型详解(反射Class.forName详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/593261

相关文章

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

MyBatis配置文件中最常用的设置

《MyBatis配置文件中最常用的设置》文章主要介绍了MyBatis配置的优化方法,包括引用外部的properties配置文件、配置外置以实现环境解耦、配置文件中最常用的6个核心设置以及三种常用的Ma... 目录MyBATis配置优化mybatis的配置中引用外部的propertis配置文件⚠️ 注意事项X

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param