当前位置: 首页 > news >正文

Day12

1. 链表和数组有什么区别?

在存储方式上,数组是连续内存存储,所有元素在内存中是连续排列的,因此可以通过下标快速访问(O(1)),但插入、删除操作代价高,需要移动后续元素(O(n))。而链表是非连续存储,每个元素是一个节点,包含数据和指向下一个节点的指针,因此插入、删除效率高(O(1)),但查找元素需要从头开始遍历(O(n))。此外,数组的大小是固定的(除非使用动态数组如 ArrayList),而链表是动态扩容的,适合不确定大小的场景。
数组适合查找频繁、元素数量固定的场景;链表适合插入删除频繁、元素数量动态变化的场景。

2. 如何使用两个栈实现队列?

使用两个栈(我们称为 inStack 和 outStack)可以实现一个先进先出(FIFO)的队列。核心思想是:

  • 入队操作(enqueue):直接压入 inStack。
  • 出队操作(dequeue):如果 outStack 为空,则将 inStack 中的所有元素弹出并依次压入 outStack,然后从 outStack 弹出栈顶元素。

把一个栈当作输入端,另一个当作输出端,每当需要出队时,把输入栈的元素全部倒入输出栈,从而实现先进先出。

import java.util.Stack;public class MyQueue {private Stack<Integer> inStack = new Stack<>();private Stack<Integer> outStack = new Stack<>();// 入队public void enqueue(int x) {inStack.push(x);}// 出队public int dequeue() {if (outStack.isEmpty()) {while (!inStack.isEmpty()) {outStack.push(inStack.pop());}}if (outStack.isEmpty()) {throw new RuntimeException("Queue is empty");}return outStack.pop();}// 获取队首元素但不出队public int peek() {if (outStack.isEmpty()) {while (!inStack.isEmpty()) {outStack.push(inStack.pop());}}if (outStack.isEmpty()) {throw new RuntimeException("Queue is empty");}return outStack.peek();}public boolean isEmpty() {return inStack.isEmpty() && outStack.isEmpty();}
}

3. MySQL的三大日志说一下,分别应用场景是什么?

  • Redo Log(重做日志):是 InnoDB 存储引擎特有的,用来记录已经提交事务对数据的修改,它保证了即使数据库宕机,只要事务提交了,就可以通过 redo Log 把数据恢复到正确状态,应用场景比如数据库崩溃后重启恢复。
  • undo Log(回滚日志):也是 InnoDB 的日志,记录的是事务修改前的数据,用来支持事务的回滚功能,确保在事务失败或主动回滚时可以恢复现场,同时它还支持 MVCC,实现数据库的非阻塞读。
  • binlog(二进制日志):属于 MySQL层,记录了所有对数据库数据的更改操作,比如 INSERT、UPDATE、DELETE等,它的主要用途是主从复制和数据恢复,比如主库把 binlog 同步到从库,或者用来做增量备份恢复数据。
日志类型举例操作什么时候用
redo log崩溃后还能恢复转账数据保证事务提交后数据不丢
undo log撤销更新操作,快照读支持事务回滚、MVCC 快照读取
binlog主从复制、恢复历史数据数据备份、恢复、数据库同步

4. Spring的IOC介绍一下?

IOC 全称是 Inversion of Control,中文叫做“控制反转”,它是一种设计思想,不特指某个技术或框架。在 Spring中,IOC 的核心含义是:对象的创建、初始化、以及它所依赖的其他对象的注入,不再由我们自己控制,而是交给 Spring 容器负责。
Spring 是通过依赖注入(DI)机制来实现控制反转,即:你不需要创建依赖对象,而是通过注入的方式由 Spring 自己提供。

注入方式描述说明示例注解或语法
构造器注入在创建对象时通过构造方法传入依赖对象(强依赖推荐)@Autowired构造器
Setter注入在对象创建后通过setter方法注入依赖对象(可选依赖)@Autowired 方法
字段注入直接在字段上标注注解,Spring 反射注入(简洁但不易测试)@Autowired 字段
Java配置注入使用 @Bean 方法手动注册 Bean 并注入@Configuration
好处说明
解耦合类之间通过接口而非具体实现耦合,增强了灵活性
易测试可通过 Mock 对象轻松替换依赖,适合单元测试
易扩展维护不同实现类可以随时替换(只需修改配置),实现“开闭原则”
统一管理生命周期Spring 控制 Bean 的创建、销毁等生命周期,开发者只关注业务逻辑

传统的 Java SE 程序设计中,我们直接在对象内部通过 new 的方式来创建对象,是程序主动创建依赖对象。

在这里插入图片描述

在这里插入图片描述

5. 为什么依赖注入不适合使用字段注入?

字段注入可能引起三个问题:

  1. 对象的外部可见性差,依赖不可见:字段注入是通过反射进行的,注入的依赖对象在类的构造方法中看不到,外部也不清楚这个类到底依赖了什么对象,不利于阅读、理解和维护代码,也违背了依赖显示原则。
  2. 可能导致循环依赖:字段注入在 Spring 中是实例化对象后通过反射注入的,这比构造器注入更晚。所以放发生循环依赖时(A 注入 B,B 注入 A),字段注入可能不会立即暴露出来,出错位置不明显,难以排查和调试。
    构造器注入的循环依赖是 Spring 无法处理的,启动时就会报错,反而更容易发现问题;字段注入可能导致隐式循环依赖,运行中才报错。
  3. 无法使用 final 修饰符,也无法注入静态变量:字段注入发生在对象创建之后,Spring 是通过反射设置字段的,所以不能注入 final 字段(编译器会禁止反射修改 final 值)。同样静态变量也不能注入,因为它属于类本身而不是某个对象实例。

6. Spring的AOP介绍一下?

AOP 全称是 Aspect-Oriented Programming(面向切面编程)。它把那些在多个模块中都会用到的、但跟主业务逻辑无关的代码(比如日志、安全、事务、缓存)提取出来单独编写成一个“切面类”,统一管理,减少重复,提高代码清晰度。
AOP 的核心概念包括连接点、切点、通知、切面和织入,Spring 通过 JDK 动态代理或 CGLIB 实现织入。我们可以通过 @Aspect 和一系列注解来定义切面,常见的场景包括日志记录、权限控制、事务管理等。

概念中文作用
JoinPoint连接点可能被拦截的方法执行点(如某个 service 方法)
Pointcut切点明确拦截哪些连接点(通过表达式来定义)
Advice通知要织入的方法逻辑,分为前置、后置、环绕等
Aspect切面Pointcut + Advice 的组合
Weaving织入把 Advice 和业务方法组合的过程,Spring 用代理实现

Spring AOP 是通过 代理机制 实现的:

  • 如果目标类实现了接口 → 使用 JDK 动态代理
  • 如果目标类没有实现接口 → 使用 CGLIB 生成子类字节码代理

所以 AOP 只对 Spring 容器管理的 Bean 有效,自己 new 出来的对象不会生效。

7. Spring的事务,使用this调用是否生效?

在同一个类中,使用 this 调用被 @Transactional注解的方法,事务通常不会生效。

  1. Spring 事务管理基于 AOP(面向切面编程)实现:当你给一个方法加上@Transactional注解时,Spring 并不会直接修改你的原始类(目标对象)。Spring 会创建一个代理对象(Proxy)来“包裹”你的目标对象。这个代理对象负责在目标方法执行前后添加事务管理逻辑(开启事务、提交/回滚事务等)。
  2. 代理对象的工作方式:外部代码(比如另一个类中的方法)调用你的@Transactional方法时,实际上调用的时这个代理对象上的方法。代理对象先进行事务处理(如开启事务),然后再调用目标对象内部真正的对应方法。这时事务逻辑才得以执行。
  3. this 调用破坏了代理机制:当你在同一个类的一个方法(比如方法 A)中,使用this.xxx()调用另一个被@Transactional注解的方法(比如方法 B)时,这个 this 关键字指向的是当前类的原始目标对象本身,而不是 Spring 创建的代理对象。因为调用发生在目标对象内部,它直接调用了自身的方法 B,完全绕过了外部的代理对象。既然代理对象没有介入,那么代理对象添加的事务管理逻辑(开启事务等)也就根本不会执行。方法B虽然被注解了,但就像没有注解一样运行在无事务环境中。

8. Spring MVC的工作流程描述一下?

当用户发送请求后,Spring MVC 的核心组件DispatcherServlet首先接收到这个请求。它通过HandlerMapping查找对应的处理器(Controller),并返回一个包含处理器及其拦截器的执行链。接着由HandlerAdapter调用实际的 Controller 方法,同时完成参数封装、数据校验等操作。Controller 处理完业务逻辑后返回一个ModelAndViewDispatcherServlet会将它交给ViewResolver来解析具体的视图对象(如JSP)。最后,DispatcherServlet渲染视图,把数据填充进去后返回给客户端完成响应。整个流程体现了请求分发、控制器处理、视图渲染的解耦,保证了 Spring MVC 的灵活性和扩展性。

在这里插入图片描述

相关文章:

  • 智能全能邮箱:是否真能替代企业邮箱系统?
  • postman自动化测试
  • Linux基本指令(三)
  • 得力Deli GE330W打印机信息
  • JAVA-springboot JOSN解析库
  • fmod产生的误差应该如何解决?
  • 前端判断内容文字是否溢出容器,创建临时元素来模拟文本实际宽度
  • thymeleaf直接调用Spring Bean中定义的方法
  • Maven 构建缓存与离线模式
  • SSM spring Bean基础配置
  • simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应
  • linux 故障处置通用流程-36计+1计
  • 比较运算符:==、!=、>、<、>=、<=
  • 【C/C++】进一步介绍idl编码
  • 《动手深度学习》8.2文本预处理—代码分析
  • 运行labelme
  • java day15 (数据库)
  • Oracle实用参考(13)——Oracle for Linux静默安装(1)
  • FAST(Features from Accelerated Segment Test)角检测算法原理详解和C++代码实现
  • dvwa8——SQL Injection(Blind)
  • 网站值不值得做seo/嘉兴关键词优化报价
  • 品牌推广怎么做/智推教育seo课程
  • 广东网站建设微信官网开发/优化网站排名费用
  • 如何网站建设自己怎么个人网站/宁德市属于哪个省份
  • wordpress单位内网做网站/优化系统
  • wordpress购物网站/搜索引擎营销总结