Java笔试面试题AI答之JDBC(2)

文章目录

  • 7. 列出Java应该遵循的JDBC最佳实践?
  • 8. Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入
      • Statement与PreparedStatement的区别
      • 什么是SQL注入
      • 如何防止SQL注入
  • 9. JDBC如何连接数据库?
      • 1. 加载JDBC驱动程序
      • 2. 建立数据库连接
      • 3. 创建Statement对象
      • 4. 执行SQL语句并处理结果
      • 5. 关闭连接
      • 示例代码
  • 10. JDBC 中如何处理事务?
  • 11. JDBC是如何实现Java程序与JDBC驱动的松耦合的?
      • 1. 接口定义与实现分离
      • 2. 反射机制加载驱动
      • 3. 抽象层次高
  • 12. 简述JDBC的Driver Manager的作用 ?
      • 1. 管理JDBC驱动程序
      • 2. 创建数据库连接
      • 3. 连接池的支持(间接)
      • 4. 安全性和隔离性

7. 列出Java应该遵循的JDBC最佳实践?

在Java中,遵循JDBC最佳实践可以显著提高数据库操作的性能和安全性。以下是一些关键的JDBC最佳实践:

  1. 使用PreparedStatement

    • PreparedStatement是预编译的SQL语句,它可以显著提高性能,因为它避免了SQL语句的重复解析。
    • PreparedStatement还可以有效防止SQL注入攻击,因为它使用参数化查询,将查询中的参数与SQL语句的其余部分分开处理。
  2. 连接池化

    • 使用连接池可以管理数据库连接的创建、使用和释放,避免了频繁地创建和销毁连接的开销。
    • 连接池可以显著提高应用程序的性能和可伸缩性。
  3. 禁止自动提交事务

    • 在执行批量操作或需要多个步骤的数据库事务时,应禁用自动提交模式。
    • 这允许将多个SQL语句组合成一个事务,并在完成后一次性提交,从而提高了性能并确保了数据的一致性。
  4. 使用JDBC批量操作

    • 对于需要插入、更新或删除大量记录的场景,应使用JDBC的批处理功能。
    • 批处理可以显著减少与数据库的交互次数,从而提高性能。
  5. 优化SQL语句

    • 编写高效的SQL语句,避免使用SELECT *,只选择需要的字段。
    • 使用索引来加速查询操作。
    • 尽量避免复杂的子查询和连接操作,以减少查询的复杂度和执行时间。
  6. 合理设置事务边界和隔离级别

    • 根据应用程序的需求,合理设置事务的边界和隔离级别。
    • 避免不必要的事务开销,只在需要的时候开启事务。
  7. 使用查询缓存

    • 对于频繁查询且结果不变的数据,可以考虑使用查询缓存来减少数据库的访问次数。
  8. 监控数据库性能

    • 使用数据库监控工具来监控数据库的性能,找出性能瓶颈并进行调优。
  9. 调整JVM参数

    • 根据应用程序的需求和硬件环境,调整JVM的参数,如堆大小、垃圾回收算法等,以提高Java应用程序的性能。
  10. 定期更新数据库驱动

    • 使用最新版本的数据库驱动,以利用其中的性能改进和错误修复。
  11. 安全性考虑

    • 除了使用PreparedStatement来防止SQL注入外,还应确保数据库连接的安全性,如使用加密连接、限制数据库用户的权限、使用安全的认证机制等。
    • 对数据库输入进行验证和过滤,以防止恶意输入导致的安全问题。

这些JDBC最佳实践可以帮助Java开发者编写更高效、更安全、更可维护的数据库应用程序。遵循这些实践不仅可以提高应用程序的性能,还可以降低维护成本并增强系统的安全性。

8. Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入

Statement与PreparedStatement的区别

Statement与PreparedStatement都是JDBC(Java Database Connectivity)API中用于执行SQL语句的接口,但它们之间存在显著的差异:

  1. 功能和使用场景

    • Statement:用于执行静态的SQL语句。它适用于执行简单的、不需要重复执行或参数化的SQL语句。由于每次执行都需要编译SQL语句,因此效率相对较低,特别是在执行大量相同或相似的SQL语句时。
    • PreparedStatement:继承自Statement,但增加了预编译功能。它适用于执行需要多次执行且可能带有参数的SQL语句。PreparedStatement在执行前会对SQL语句进行预编译,并将编译结果缓存起来,以提高执行效率。同时,它支持使用占位符(如?)来代表参数,避免了SQL语句的拼接,提高了安全性。
  2. 安全性和SQL注入

    • Statement:由于它是直接将用户输入拼接到SQL语句中,因此容易遭受SQL注入攻击。攻击者可以通过在输入中插入恶意的SQL代码来篡改原有的SQL语句,执行非预期的操作。
    • PreparedStatement:通过使用占位符和设置参数的方式,PreparedStatement有效地防止了SQL注入攻击。因为参数在传递到数据库之前,不会被当作SQL语句的一部分来解析,从而避免了恶意SQL代码的执行。
  3. 执行效率

    • Statement:每次执行都需要编译SQL语句,这可能会导致数据库缓冲区溢出或性能下降。
    • PreparedStatement:由于具有预编译和缓存功能,其执行效率通常高于Statement。特别是对于大量相同的SQL语句执行,性能优势更为明显。

什么是SQL注入

SQL注入是一种代码注入技术,攻击者通过在Web表单提交或输入域名、页面请求的查询字符串中插入(或“注入”)恶意的SQL命令,来破坏后端数据库。这种攻击利用了Web应用程序对用户输入数据的合法性判断不足或过滤不严的漏洞,使攻击者能够非法访问或操作数据库中的数据。SQL注入可能导致数据泄露、数据篡改、甚至整个系统被攻击者控制。

如何防止SQL注入

防止SQL注入的方法有多种,主要包括以下几种:

  1. 使用参数化查询:参数化查询(如PreparedStatement)是最常见也是最有效的防止SQL注入的方法之一。通过将用户输入的数据作为参数传递给SQL查询语句,而不是将其直接拼接到查询语句中,可以避免SQL注入攻击。

  2. 输入验证和过滤:对用户输入的数据进行严格的验证和过滤,确保数据符合预期的格式和类型。特别是对于特殊字符(如单引号、分号等),应该进行转义或删除,以防止其被用作SQL注入的一部分。

  3. 使用ORM框架:ORM(对象关系映射)框架可以帮助开发人员更方便地操作数据库,同时提供一定的安全性。ORM框架通常会对用户输入进行自动转义和过滤,从而减少SQL注入的风险。

  4. 最小权限原则:为数据库用户分配最小权限,确保他们只能执行必要的操作。这样即使发生了SQL注入攻击,攻击者也只能在有限的权限范围内进行操作,减少了攻击的危害。

  5. 定期更新和维护数据库:及时安装数据库厂商提供的安全更新和补丁,以修复已知的漏洞。同时,定期检查和清理数据库中的无效数据和过期数据,保持数据库的整洁和安全性。

9. JDBC如何连接数据库?

JDBC(Java DataBase Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,它允许Java程序与数据库进行交互。JDBC连接数据库的过程通常遵循以下步骤:

1. 加载JDBC驱动程序

在连接数据库之前,需要加载相应的JDBC驱动程序。驱动程序是数据库供应商提供的,用于实现JDBC API与特定数据库之间的通信。加载驱动程序通常通过调用Class.forName(driverClass)方法实现,其中driverClass是驱动程序的完全限定名。例如,对于MySQL数据库,驱动类名可能是"com.mysql.cj.jdbc.Driver"(注意:驱动类名可能会随着数据库版本的更新而发生变化)。

2. 建立数据库连接

一旦驱动程序被加载,就可以使用DriverManager.getConnection(url, user, password)方法建立与数据库的连接了。这个方法需要三个参数:

  • url:数据库的JDBC URL,它包含了连接数据库所需的信息,如协议、子协议、数据源标识等。
  • user:数据库的用户名。
  • password:数据库的密码。

JDBC URL的格式通常遵循"jdbc:子协议:数据源标识"的模式,其中子协议和数据源标识取决于所使用的数据库和驱动程序。例如,对于MySQL数据库,JDBC URL可能类似于"jdbc:mysql://localhost:3306/数据库名?参数=值&参数=值"

3. 创建Statement对象

建立连接后,可以使用Connection对象的createStatement()方法创建一个Statement对象。Statement对象用于执行静态SQL语句并返回它所产生结果的对象。

4. 执行SQL语句并处理结果

通过Statement对象,可以执行SQL语句,并使用返回的结果集(ResultSet对象)来处理查询结果。对于更新(INSERT、UPDATE、DELETE)操作,Statement对象还提供了执行更新操作并返回受影响的行数的方法。

5. 关闭连接

完成数据库操作后,应关闭ResultSetStatementConnection对象以释放数据库资源。这通常通过调用这些对象的close()方法来实现。

示例代码

以下是一个简单的示例,展示了如何使用JDBC连接MySQL数据库并执行一个查询操作:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcExample {
    public static void main(String[] args) {
        // 加载MySQL JDBC驱动程序
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 数据库URL、用户名和密码
        String url = "jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC";
        String user = "root";
        String password = "password";

        // 建立连接
        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM mytable")) {

            // 处理查询结果
            while (rs.next()) {
                // 假设有名为"id"和"name"的列
                int id = rs.getInt("id");
                String name = rs.getString("name");
                System.out.println("ID: " + id + ", Name: " + name);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

请注意,上述代码中的数据库URL、用户名和密码需要根据实际情况进行替换。此外,serverTimezone=UTC是一个常见的连接参数,用于解决时区相关的问题,但你也可以根据需要设置其他参数。

10. JDBC 中如何处理事务?

在JDBC中处理事务主要涉及到几个关键的方法,这些方法定义在Connection接口中。事务是一组操作,它们作为一个整体一起执行,要么全部成功,要么全部失败。JDBC通过以下方式支持事务处理:

  1. 设置自动提交模式:默认情况下,JDBC的Connection对象是处于自动提交模式的(auto-commit模式),这意味着每个SQL语句都被视为一个单独的事务,并且一旦执行就立即提交到数据库。为了进行事务控制,首先需要关闭自动提交模式。

    connection.setAutoCommit(false);
    

    关闭自动提交模式后,你需要手动地提交或回滚事务。

  2. 提交事务:当一组操作成功执行后,需要调用commit方法来提交事务,这样所有的更改都会永久保存到数据库中。

    connection.commit();
    

    如果在提交事务前发生异常或错误,则应该回滚事务。

  3. 回滚事务:如果在事务执行过程中发生错误或异常,可以调用rollback方法来撤销自关闭自动提交以来对数据库所做的所有更改。

    connection.rollback();
    

    回滚后,数据库将恢复到事务开始前的状态。

  4. 异常处理:在事务处理过程中,合理的异常处理是非常重要的。通常,你会在try-catch块中执行数据库操作,并在catch块中捕获异常后调用rollback方法来确保数据的一致性。如果事务成功完成,则在finally块中调用commit方法(如果之前没有发生异常)。但是,需要注意的是,如果在try块中调用commit时发生了异常,那么你可能需要在catch块中再次调用rollback,但这通常不是必需的,因为一旦调用了commit,事务就已经结束了。

  5. 设置保存点:在某些情况下,你可能希望在事务中设置保存点(Savepoint),以便在发生特定错误时能够回滚到事务中的某个特定点,而不是回滚整个事务。这可以通过ConnectionsetSavepointrollback(Savepoint savepoint)releaseSavepoint(Savepoint savepoint)方法来实现。

  6. 资源管理:使用JDBC时,还应注意管理资源,如ConnectionStatementResultSet对象。确保在不再需要时关闭它们,以释放数据库资源。这通常通过在finally块中关闭资源来实现。

  7. 事务隔离级别:JDBC还允许你设置事务的隔离级别,以控制并发事务之间的可见性和影响。你可以通过调用ConnectionsetTransactionIsolation方法来设置隔离级别。

通过合理地使用这些JDBC事务处理特性,你可以有效地管理数据库事务,确保数据的一致性和完整性。

11. JDBC是如何实现Java程序与JDBC驱动的松耦合的?

JDBC(Java Database Connectivity)实现Java程序与JDBC驱动的松耦合,主要通过以下几个关键机制:

1. 接口定义与实现分离

JDBC API定义了一套标准的接口和类,这些接口和类位于java.sqljavax.sql包中。这些接口定义了与数据库交互所需的基本功能,如连接数据库、执行SQL语句、处理结果集等。然而,JDBC API本身并不包含这些接口的具体实现,而是由数据库厂商根据JDBC规范来提供实现。

数据库厂商会根据自己数据库的特性,实现JDBC接口中的方法,并将这些实现打包成JDBC驱动(通常是.jar文件)。Java程序在运行时,通过加载这些JDBC驱动,并调用JDBC接口中的方法,来与数据库进行交互。由于Java程序与JDBC驱动的交互是通过接口进行的,因此Java程序并不依赖于特定的JDBC驱动实现,从而实现了松耦合。

2. 反射机制加载驱动

JDBC使用Java的反射机制(Reflection)来加载JDBC驱动。在Java程序中,通常通过调用Class.forName(String className)方法来加载JDBC驱动类。这个方法的调用会触发Java的类加载机制,加载并初始化指定的JDBC驱动类。JDBC驱动类在被加载时,会将自己注册到DriverManager类中。DriverManager是JDBC提供的一个管理类,用于管理数据库驱动。

当Java程序需要连接数据库时,它会通过DriverManager.getConnection(String url, String user, String password)方法获取数据库连接。DriverManager会根据传入的URL和已经注册的JDBC驱动,找到匹配的驱动,并创建数据库连接。由于JDBC驱动是通过反射机制加载的,并且是在运行时动态地注册到DriverManager中的,因此Java程序并不需要在编译时就依赖于特定的JDBC驱动。

3. 抽象层次高

JDBC API提供了高度的抽象层次,使得Java程序可以以一种通用的方式与数据库进行交互。无论底层数据库的具体实现如何,Java程序都可以通过JDBC API来执行SQL语句、处理结果集等。这种高度的抽象层次有助于降低Java程序与数据库之间的耦合度,使得Java程序可以更容易地适应不同的数据库环境。

综上所述,JDBC通过接口定义与实现分离、反射机制加载驱动以及提供高度的抽象层次等机制,实现了Java程序与JDBC驱动的松耦合。这种松耦合的设计使得Java程序可以更容易地与不同的数据库进行交互,提高了代码的可移植性和可维护性。

12. 简述JDBC的Driver Manager的作用 ?

JDBC(Java Database Connectivity)的Driver Manager在Java数据库应用程序中扮演着关键角色,其主要作用可以归纳如下:

1. 管理JDBC驱动程序

  • 加载和注册驱动程序:Driver Manager负责加载和注册JDBC驱动程序。尽管从Java 6(也称为JDK 1.6)开始,Driver Manager能够自动加载位于类路径中的JDBC驱动程序,但为了向后兼容性和确保正确加载,许多开发者仍然会显式地通过Class.forName()方法加载驱动程序。
  • 维护驱动程序列表:Driver Manager跟踪可用的JDBC驱动程序,并在需要时选择适当的驱动程序来建立数据库连接。

2. 创建数据库连接

  • 提供数据库连接:Driver Manager通过其getConnection()方法提供数据库连接。这个方法接受数据库的连接URL、用户名和密码(如果需要的话)作为参数,并返回一个表示数据库连接的Connection对象。
  • 连接过程:当调用getConnection()方法时,Driver Manager会遍历已注册的驱动程序,尝试使用每个驱动程序建立连接。它首先会尝试使用jdbc.drivers系统属性中指定的驱动程序,然后尝试使用类路径中自动加载的驱动程序。一旦找到合适的驱动程序,Driver Manager就会使用它来建立连接。

3. 连接池的支持(间接)

  • 不直接支持连接池:需要注意的是,Driver Manager本身并不直接支持连接池功能。连接池是一种用于管理数据库连接的技术,它可以显著提高应用程序的性能和响应速度。然而,Driver Manager可以与连接池一起使用,允许连接池通过Driver Manager来创建和释放数据库连接。
  • 连接池的优势:在实际应用中,通常会使用第三方连接池库(如Apache Commons DBCP、C3P0或HikariCP)来管理数据库连接。这些连接池库提供了更高级的连接管理功能,如连接复用、连接池大小调整、连接超时和空闲连接回收等。

4. 安全性和隔离性

  • 安全控制:Driver Manager还可以与Java的安全管理器(Security Manager)协作,以实施对数据库访问的安全控制。例如,可以限制哪些类加载器可以加载JDBC驱动程序,以及哪些代码可以访问特定的数据库连接。
  • 隔离性:由于Driver Manager维护了一个独立的驱动程序列表,并在需要时选择适当的驱动程序来建立连接,因此它有助于在应用程序的不同部分之间实现数据库访问的隔离性。

综上所述,JDBC的Driver Manager是Java数据库应用程序中不可或缺的一部分,它负责管理JDBC驱动程序、创建数据库连接,并间接支持连接池的使用。通过提供这些功能,Driver Manager使得Java开发者能够更方便、更高效地与数据库进行交互。

答案来自文心一言,仅供参考
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于FreeRTOS的STM32多功能手表

前言 项目背景 项目演示 使用到的硬件 项目原理图 目前版本实现的功能 设计到的freertos知识 实现思路 代码讲解 初始化GPIO引脚、配置时钟 蜂鸣器初始化以及软件定时器创建 系统默认创建的defaultTaskHandle 创建七个Task,代表七个功能 ShowTimeTask …

MySQL复习2

高级查询 准备 create database greatselect; use greatselect;drop table if exists class; create table class (cid int(11) not null auto_increment,caption varchar(32) not null,primary key (cid) )engine innoDB AUTO_INCREMENT5 default charset utf8;create tab…

磁盘加密工具 | VeraCrypt v1.26.15 绿色版

VeraCrypt 是一个开源项目,旨在提供强大的加密解决方案,以创建和管理加密的磁盘分区和加密容器。它继承了著名的加密软件 TrueCrypt 的特性,并在此基础上进行了扩展和改进。 主要特性 1. 高级加密算法 VeraCrypt 支持多种加密算法&#xf…

运维学习————Jenkins(1)

目录 一、项目开发周期 二、jenkins的简介和作用 三、jenkins下载 1、使用war包安装 2、初始化配置 3、工作流程图 4、Jenkins安装配置maven和git maven git 5、jenkins安装插件 6、配置maven,git,jdk jdk配置 Git配置 Maven配置 四、修改tomcat的一些配置 五…

[网络编程]TCP和UDP的比较 及 通过java用UDP实现网络编程

文章目录 一. 网络编程套接字TCP和UDP的特点有连接 vs 无连接可靠传输 vs 不可靠传输面向字节流 vs 面向数据报全双工 vs 半双工 二. java用UDP实现网络编程代码实现:运行代码:启动多个客户端别人能否使用?实现翻译功能 一. 网络编程套接字 网络编程套接字, 就是指操作系统提…

[000-01-008].Seata案例应用

业务说明:这里我们创建三个服务,一个订单服务,一个库存服务,一个账户服务。当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存;再通过远程调用账户服务来…

AD7606工作原理以及FPGA控制验证(串行和并行模式)

文章目录 一、AD7606介绍二、AD7606采集原理2.1 AD7606功能框图2.2 AD7606管脚说明 三、AD7606并行模式时序分析以及实现3.1 并行模式时序图3.2 并行模式时序要求3.3 代码编写3.4 仿真观察 四、AD7606串行模式时序分析以及实现4.1 串行模式时序图4.2 串行模式时序要求4.3 代码编…

使用Cskin时候 遇到按钮有默认阴影问题解决

使用Cskin时候 遇到按钮有默认阴影 设置 DrawType 属性就可以了

全网最火的AI技术:GraphRag概念详解

GraphRAG是一种结合了知识图谱(Knowledge Graph)和大语言模型(LLM)的检索增强生成(Retrieval-Augmented Generation, RAG)技术,旨在通过将结构化和非结构化数据相结合来增强生成式AI的表现。它的…

[已更新问题二三matlab+python]2024数学建模国赛高教社杯C题:农作物的种植策略 思路代码文章助攻手把手保姆级

发布于9.6 10:00 有问题后续会修正!! 问题一代码展示: 问题二代码结果展示: 问题三代码展示: https://docs.qq.com/doc/DVVVlV0NmcnBDTlVJ问题一部分代码分享: #!/usr/bin/env python # coding: utf-8# In[15]:import pandas as pd# In[16]:# 读取Excel文件 file_path 附件2…

【数学建模备赛】Ep07:灰色预测模型

文章目录 一、前言🚀🚀🚀二、:灰色预测模型☀️☀️☀️1. 灰色系统引入2. 方法3. 步骤① 累加法产生新序列② 利用部分和序列相邻两项的加权平均产生序列z③ 建立关于原始数据与序列z的灰微分方程④ 利用最小二乘法确定灰微分方程…

win10添加右键菜单打开VSCode

当进入一个文件夹后,想右键直接打开我的工程,用发现没有vscode项。本文就来介绍如何右键通过vsCode打开项目。步骤1:在桌面新建一个txt文档,用文本编辑器打开 步骤2: 查看vscode所在位置 在桌面找到vscode快捷键图标&…

【大规模语言模型:从理论到实践】Transformer中PositionalEncoder详解

书籍链接:大规模语言模型:从理论到实践 第15页位置表示层代码详解 1. 构造函数 __init__() def __init__(self, d_model, max_seq_len80):super().__init__()self.d_model d_model # 嵌入的维度(embedding dimension)d_mode…

基于springboot的二手车交易系统的设计与实现

题目:基于springboot的二手车交易系统的设计与实现 摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因…

【书籍推荐】马斯克推荐的5部经典书籍

埃隆马斯克是谁想必已经不需要介绍,世界首富都推荐过哪些值得看的好书?今天这篇文章整理了5本马斯克曾推荐过或评价值得一读的书,或许可以从中一探他改变世界的方法和奥秘。 《结构是什么》 结构高于内容,结构决定内容。内容是表…

C++笔记15•数据结构:二叉树之二叉搜索树•

二叉搜索树 1.二叉搜索树 概念: 二叉搜索树又称二叉排序树也叫二叉查找树,它可以是一棵空树。 二叉树具有以下性质: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都…

vue3+ts封装类似于微信消息的组件

组件代码如下&#xff1a; <template><div:class"[voice-message, { sent: isSent, received: !isSent }]":style"{ backgroundColor: backgroundColor }"click"togglePlayback"><!-- isSent为false在左侧&#xff0c;为true在右…

十分钟简单了解Java中的数据类型和变量!

一.字面常量 public class test{public static void main(String[] args){system.out.println("Hello world!");} }在上述代码中&#xff0c;system.out.println(“Hello world!”);语句不管何时运行&#xff0c;输出的结果都是Hello world!,其实Hello world&#xf…

Obsidian git sync error / Obsidian git 同步失敗

Issue: commit due to empty commit message Solution 添加commit資訊&#xff0c;確保不留空白 我的設置&#xff1a;auto-backup: {{hostname}}/{{date}}/

虚幻引擎(Unreal Engine)技术使得《黑神话悟空传》大火,现在重视C++的开始吃香了,JAVA,Go,Unity都不能和C++相媲美!

虚幻引擎&#xff08;Unreal Engine&#xff09;火了黑神话游戏。 往后&#xff0c;会有大批量的公司开始模仿这个赛道&#xff01; C 的虚拟引擎技术通常指的是使用 C 语言开发的游戏引擎&#xff0c;如虚幻引擎&#xff08;Unreal Engine&#xff09;等。以下是对 C 虚拟引…