Java 全栈开发工程师面试题2025 年 3 月 17 日 | 阅读 26 分钟 全栈开发工程师是能够同时处理网站和应用程序的**前端和后端**的熟练程序员。他们负责开发和设计前端/后端 Web 架构、服务器端应用程序、设计数据库、服务器端应用程序等等。 正因如此,科技巨头们会招聘全栈开发工程师并进行面试。如果你为**全栈开发工程师面试**做好了充分准备,那么你被公司录用的机会就会增加。在本节中,我们收集了一些**全栈开发工程师面试题**,它们可以帮助你通过面试,找到心仪的工作。 在过去的几年里,**全栈开发工程师**的职位需求一直在增长,因为他们能够处理不同的技术和语言。此外,全栈开发工程师还擅长解决应用程序或 Web 开发的各个阶段出现的异常问题。 ![]() 1) 全栈开发工程师应该了解什么?Java 全栈开发工程师需要全面理解前端和后端开发,同时熟练掌握 Java 及相关技术。 1. 核心 Java
2. Java 框架
3. 前端技术
4. Web 开发概念
5. 数据库管理 6. 版本控制系统
7. 开发工具
8. DevOps
9. 软技能
2) 什么是 MVC 和 MVP?MVC 与 MVP 有何不同?MVC 和 MVP 都是用于开发应用程序的架构模式。 MVC MVC 代表**模型-视图-控制器**。它是一种用于开发 Java 企业应用程序的架构模式。它将应用程序分为三个逻辑组件:**模型、视图**和**控制器**。它将特定于业务的逻辑(模型组件)与表示层(视图组件)相互分离。 模型组件包含与其相关的数据和逻辑。视图组件负责在用户界面中显示模型对象。控制器接收输入,并根据处理程序映射调用模型对象。它还将模型对象传递给视图,以便在视图层中显示输出。 ![]() MVP MVP 代表**模型-视图-呈现器**。它源自 MVC 架构模式。它在架构模式中增加了一个额外的层(称为间接层),将视图和控制器分成视图和呈现器。控制器的角色被呈现器取代。它与 MVC 中的视图处于同一级别。它包含视图的 UI 业务逻辑。从视图接收的调用会直接发送给呈现器。它维护视图和模型之间的操作(事件)。呈现器不直接与视图通信。它通过接口进行通信。 ![]() MVC 和 MVP 架构模式之间的主要区别在于,在 MVC 架构模式中,控制器不将数据从模型传递给视图。它只通知视图自行从模型获取数据。 而在 **MVP** 架构模式中,视图和模型层是相互连接的。呈现器本身从模型接收数据,并将其发送给视图进行显示。 另一个区别是 MVC 通常用于 Web 框架,而 MVP 用于应用程序开发。 ![]() 3) 什么是结对编程?结对编程是一种敏捷软件开发技术,其中两个程序员在一个工作站上协同工作。一名程序员担任“驾驶员”,负责**编写**代码,而另一名程序员担任“**观察员**”或“**导航员**”,负责在代码输入时**审查**每一行代码。两名程序员会频繁地交换角色。 驾驶员可能专注于实现核心 Java 功能或设置 Spring Boot 项目,而导航员则提供有关最佳实践的见解,确保遵守设计模式,或提出改进建议。对于前端开发,一个人可能专注于用 Angular 或 React 编码,而另一个人则检查最佳的 UI/UX 设计和跨浏览器兼容性。这种编程技术更有效率,可以将编码错误降至最低。结对编程的缺点是会增加成本。 结对编程有助于确保前端和后端组件都得到良好的集成,并在整个开发过程中保持应用程序的高质量标准。 4) MVC 中的 CORS 是什么?它是如何工作的?CORS 代表**跨源资源共享**。它是一种 **W3C** 标准和基于 HTTP 头的机制。它允许服务器指示除请求之外的任何其他源(如域、端口等)。换句话说,它允许一个网站使用 JavaScript 访问另一个网站的资源。 它支持安全的跨源请求,并在服务器和浏览器之间传输数据。高级浏览器在 API 中使用 CORS。与 JSONP(填充式 JSON)相比,它更灵活、更安全。它提供了更好的 Web 服务集成。 ![]() 在使用 MVC 实现 CORS 时,可以使用相同的 CORS 服务,但不能使用相同的 CORS 中间件。我们可以为特定操作、特定控制器以及全局所有控制器使用特定的 CORS。 浏览器会向服务器(托管跨源资源的服务器)发送一个预检请求,以确保服务器允许实际请求。例如,通过 https://demo.com 调用 URL https://example.com。 ![]() 5) 如何提高网站的可伸缩性和效率?提高网站的可伸缩性和效率涉及优化其设计和实现的各个方面。以下是对每种方法的说明: 减少 DNS 查找 DNS 查找可能非常耗时,因为浏览器在加载资源之前需要将域名解析为 IP 地址。减少网站上使用的唯一域名数量可以最大程度地减少所需的 DNS 查找次数,从而加快加载过程。 避免 URL 重定向 URL 重定向会引入额外的 HTTP 请求并增加延迟,从而减慢页面加载时间。最小化或消除重定向可确保用户能够更快、更有效地访问所需资源。 避免重复代码 重复的代码会膨胀网页,导致加载时间变慢和处理时间增加。确保每段功能或样式只定义一次,可以减少浏览器需要解析和执行的代码量,从而提高整体性能。 避免不必要的图片 大型或过多的图片会显著减慢网站速度。通过仅使用必需的图片,优化其大小和格式,并利用懒加载等技术,可以提高网站的加载时间和性能。 利用浏览器缓存 浏览器缓存会将网站的一部分(如图片、样式表和脚本)存储在用户的设备上。当用户再次访问网站时,可以从缓存加载这些资源,而无需再次下载,从而大大缩短加载时间并减轻服务器负载。 延迟 JavaScript 解析 JavaScript 的解析和执行会阻塞网页的渲染。通过在初始页面加载后延迟 JavaScript 的解析,可以更快地显示主要内容,从而提高用户感知的加载时间。 避免内联 JavaScript 和 CSS 内联 JavaScript 和 CSS 会增加 HTML 文档的大小,并阻止浏览器有效地缓存这些资源。将 JavaScript 和 CSS 分离到外部文件中,可以使浏览器在不同页面之间缓存和重用它们,从而缩短加载时间。 使用 srcset 实现响应式图片 srcset 属性允许开发人员为不同的屏幕尺寸和分辨率指定不同的图像源。这可确保浏览器下载最适合用户设备的图像,从而提高加载时间并减少不必要的数据传输。 将所有资源放在无 Cookie 域上,最好使用 CDN Cookie 会为每个 HTTP 请求添加额外数据,从而减慢静态资源的传输速度。从无 Cookie 域提供资源可避免此开销。此外,使用内容分发网络 (CDN) 将资源放置在离用户更近的服务器上,可以减少延迟并提高加载时间。CDN 还有助于分发负载,提高网站的可伸缩性。 通过实施这些优化技术,您可以显著提高网站的可伸缩性和效率,从而获得更快的加载时间、更好的用户体验,并能够处理更多的流量。 6) Get 和 Post 请求之间有什么区别?
7) 函数式编程中的引用透明性是什么意思?如果程序中任何两个具有相同值的表达式可以被替换到程序中的任何位置而不会改变程序的运行结果,那么该程序就具有引用透明性。它用于函数式编程。例如,考虑以下代码片段 如果 fun(x) 的值没有被反映出来,变量 **count1** 和 **count2** 将相等。如果 count1 和 count2 不相等,则违反了引用透明性。 8) 什么是 RESTful API?REST 代表表征状态转移 (Representational State Transfer)。它是一种用于创建Web 服务的架构风格。它使用 HTTP 请求来访问和使用数据。我们可以创建、更新、读取和删除数据。 网站的 API(应用程序编程接口)是允许两个软件程序相互通信的代码。它允许我们请求操作系统或其他应用程序的服务。 RESTful API 的关键特性
RESTful 示例 电子商务应用程序 在电子商务应用程序中,RESTful API 可以管理产品、客户和订单。
社交媒体平台 对于社交媒体平台,RESTful API 可以管理用户、帖子和评论。
9) 什么是 Promise,也请解释它的状态?Promise 是一个对象,它可以从异步函数同步返回。它可能有以下三种状态:
当且仅当 Promise 未处于待定状态时,它才会被结算(settled)。 10) 如何减少 Web 应用程序的加载时间?优化 Web 应用程序的加载时间对于提供流畅的用户体验至关重要。
通过实施这些优化技术,我们可以显著减少 Web 应用程序的加载时间,从而提高用户满意度和参与度。 11) 什么是持续集成和持续交付 (CI/CD)?CI/CD 是一种最佳实践,用于开发应用程序,其中代码更改更加频繁和快速。有时,它也被称为**CI\CD 流水线**。它广泛用于 DevOps,也是一种敏捷方法。 持续集成是一种编码理念或部署实践,其中开发人员每天多次将他们的代码集成到共享存储库中。因为现代应用程序需要在不同的平台上开发代码。持续集成的目标是建立一个自动化机制来构建、测试和打包应用程序。 持续交付从 CI 结束的地方开始。它会自动将应用程序交付给选定的基础设施。CD 确保在代码发生任何更改时都能自动交付代码。 12) 设计应用程序最常使用的架构设计有哪些?理解不同的架构设计模式对于创建健壮、可伸缩且可维护的软件应用程序至关重要。 1. 模型-视图-控制器 (MVC)
示例 使用 Spring MVC(在 Java 中)等 Web 应用程序,其中控制器处理 HTTP 请求,模型代表数据实体,视图将数据呈现给用户。 2. 主从模式 (Master-Slave Pattern)
示例 数据库复制,其中主数据库处理所有写入并将更改传播到从数据库,从数据库处理读取请求。 3. 分层模式 (Layered Pattern)
示例 具有用户界面、业务逻辑和数据访问等独立层的企业应用程序,例如使用 Java EE 平台构建的应用程序。 4. 模型-视图-呈现器 (MVP)
示例 桌面应用程序和 Android 应用程序,其中呈现器处理用户输入并相应地更新视图。 5. 单体架构 (Monolithic Architecture) 一个单一的、统一的应用程序,其中所有组件都相互连接和相互依赖。这是一种传统的模型,整个应用程序作为一个单元进行开发和部署。 示例 小型到中型应用程序,其中将整个系统作为一个单元进行部署和扩展是可行的,例如 Web 应用程序的早期版本。 6. 事件驱动架构模式 (Event-Driven Architecture Pattern)
示例 实时系统,如股票交易平台或物联网应用程序,其中来自传感器的事件会立即得到处理和响应。 通过利用这些架构设计模式,软件开发人员可以构建有组织、可维护且可扩展的应用程序,每种模式都适合不同类型的应用程序和项目需求。 13) 什么是长轮询?长轮询是一种有效的创建稳定服务器连接的方法,而无需使用 WebSocket 或服务器端事件协议。它运行在传统的客户端-服务器模型的顶层。请注意,Node.js 正在使用相同的技术作为下一个开发模型。 在这种方法中,客户端发送请求,服务器在连接打开期间响应,直到包含新颖的独特信息。一旦服务器响应,就可以提交对客户端的请求。当数据可用时,服务器将返回一个查询。当客户端应用程序停止并且服务器结束请求时,它就会起作用。 14) 解释语义 HTML 的含义,举例说明,以及我们为什么要使用它?在网页设计中,使用 HTML 元素来指示它们实际含义的想法。它被称为语义 HTML 或**语义标记**。 语义 HTML 是表示网页含义而非仅表示呈现的 HTML。例如,<p> 标签表示其中包含一个段落。它既是语义的也是呈现的,因为用户知道段落是什么,浏览器也知道如何显示它们。另一方面,像 <b> 和 <i> 这样的标签不是语义的。它们只表示文本的外观。这些标签不为标记提供任何附加含义。 语义 HTML 标签的示例是**标题标签** <h1> 到 <h6>、<abbr>、<cite>、<tt>、<code>、<blockquote>、<em> 等。还有一些其他的语义 HTML 标签用于构建符合标准的网站。 我们应该出于以下原因使用语义 HTML:
15) JavaScript 中的 null 与 undefined 有何区别?Null:Null 表示一个变量被赋值为**null** 值。如果将其与typeof 运算符一起使用,它会返回**object** 作为结果。我们不应该将变量赋值为 null,因为程序员使用它来表示一个没有值的变量。请注意,JavaScript 永远不会自动将值赋给 null。 Undefined:Undefined 表示变量已声明但未为其分配任何值。它可能是变量本身不存在。如果将其与 typeof 运算符一起使用,它将返回 undefined 的结果。它在 JSON 中无效。 注意:Null 和 undefined 都是原始类型。让我们通过一个例子来理解。 执行上述代码时,会生成以下输出: 从上面的输出中,我们可以观察到 var1 的值为 undefined,其类型也为 undefined。因为我们没有为变量 var1 赋值。值 null 被赋给了变量 var2。它打印其类型为 object。由于 null 是一个赋值值,我们可以将其赋值给一个变量。因此,JavaScript 将 null 和 undefined 相对平等地对待,因为它们都代表一个空值。 16) GraphQL 与 REST 的主要区别是什么?REST 和GraphQL都是 API 设计架构,可用于开发 Web 服务,尤其适用于数据驱动的应用程序。
17) 比较 fail-fast 和 fail-safe 迭代器?
18) Java 中的连接泄漏是什么?我们该如何修复它?在 Java 中,连接泄漏是指开发人员忘记关闭 JDBC 连接的情况。这是最常见的 Java 开发中遇到的连接泄漏类型,特别是在使用连接池(如 DBCP)时。我们可以通过关闭连接和特别注意错误处理代码来修复它。 19) Servlet 中有哪些不同的会话管理方法?会话是客户端和服务器之间的对话状态,可以包含客户端和服务器之间的多个请求和响应。因此,HTTP 和 Web 服务器都是无状态的,维持会话的唯一方法是将有关会话的唯一信息(会话 ID)在每个请求和响应之间传递。我们可以使用以下方法来维护会话: 1. 用户身份验证:用户身份验证涉及根据凭据(用户名和密码)验证用户的身份。成功验证后,用户的会话会通过会话令牌或 Cookie 来维持。 工作原理:成功登录后,服务器会生成一个会话令牌并将其发送给客户端。此令牌包含在后续请求中以维护会话。可以使用 HTTP 基本身份验证、基于表单的身份验证或 OAuth 等身份验证机制。 2. HTML 隐藏字段:HTML 表单中的隐藏字段可用于在客户端和服务器之间存储和发送会话信息。 工作原理:将隐藏字段添加到具有会话特定数据的 HTML 表单中。提交表单时,隐藏数据将连同可见表单数据一起发送回服务器,允许服务器识别会话。 局限性:此方法仅限于使用表单的场景,并且需要谨慎处理以避免安全问题(如篡改)。 3. Cookie:Cookie 是存储在客户端的小块数据,并在每个 HTTP 请求中发送到服务器。 工作原理:服务器创建一个会话 ID,并通过 Cookie 发送给客户端。客户端存储 Cookie,并在后续请求中包含它。服务器使用 Cookie 中的会话 ID 来检索会话信息。 优点:Cookie 是自动的,并且可以透明地工作,而无需更改 URL 或表单。 局限性:用户可以在其浏览器中禁用 Cookie,这可能会影响会话管理。 4. URL 重写:URL 重写涉及将会话信息附加到 Web 资源的 URL。 工作原理:会将会话 ID 作为查询参数附加到应用程序的 URL 中。例如,http://example.com/page?sessionid=12345。每个请求都包含 URL 中的会话 ID,允许服务器跟踪会话。 优点:即使禁用了 Cookie 也能正常工作。 局限性:需要修改 URL 并确保在所有链接和表单中都包含会话 ID。它还可能在浏览器历史记录和日志中暴露会话 ID。 5. 会话管理 API:Java Servlet API 通过 HttpSession 接口提供对会话管理的内置支持。 工作原理:当客户端发出请求时,服务器会检查会话是否存在。如果不存在,则创建一个新会话,并分配一个唯一的会话 ID,该 ID 通过 Cookie 或 URL 重写发送给客户端。服务器使用会话 ID 来检索和管理会话数据。 优点:通过提供创建、访问和使会话无效的标准方法,简化了会话管理。它抽象了用于维护会话的底层机制(Cookie、URL 重写)。 20) ServletContext 与 ServletConfig 有何区别?
21) 什么是 RequestDispatcher?RequestDispatcher 是一个接口,用于将请求转发到应用程序中可以成为HTML、JSP 或另一个Servlet 的另一个资源。我们还可以使用它将另一个资源的内容包含在响应中。该接口包含 forward() 和 include() 两个方法。 RequestDispatcher 类的常用方法 forward() 方法 语法 目的:将当前 Servlet 的请求转发到另一个资源以进行进一步处理。目标资源接管请求处理。 用法:通常在目标资源需要完全处理请求时使用,例如将请求委托给另一个 Servlet 进行专门处理。 include() 方法 语法 目的:将另一个资源的内容包含在当前响应中。在包含的内容处理完成后,控制权将返回给调用 Servlet 以继续处理。 用法:适用于将内容(如页眉、页脚或导航栏)动态包含到响应中。 ![]() 22) 构造函数注入和 setter 注入之间有什么区别?
23) Spring MVC 框架中有多少种处理异常的方法?Spring MVC 框架提供以下几种处理异常的方法:
24) Hibernate 相较于 JDBC 有哪些优势?Hibernate 相较于JDBC 有以下优势:
25) 什么是回调地狱?如何解决它?回调地狱是 JavaScript 中一种现象,在这种现象中,开发人员试图一起执行多个异步操作。嵌套回调函数的方式,使代码容易出错、难以阅读且难以维护。 我们可以通过以下方法轻松解决它: 将大型函数分解为小型函数
使用 Promise
26) Java 中的双花括号初始化是什么?在哪里使用?在 Java 中,双花括号初始化是两个独立过程的组合。其中涉及两个连续的花括号 **{{**。 第一个花括号代表**匿名内部类**的创建。请记住,在这种情况下,第二个花括号将不被考虑。这就像创建一个匿名内部类。 第二个花括号代表我们已经在类中看到的**初始化块**,用于初始化。当我们为匿名内部类使用初始化块时,它就变成了 Java 双花括号初始化。该内部类有一个指向外部类的引用。我们可以使用 **this** 指针来引用。 它用于初始化集合,因为使用双花括号初始化更容易初始化常量集合。双花括号初始化的示例如下: 27) 如何避免 Java 中的死锁?避免不必要的锁:我们应该只在需要时才使用锁。不必要的锁使用会导致死锁情况。建议使用无锁数据结构。如果可能,保持代码无锁。例如,不要使用同步的ArrayList,而是使用ConcurrentLinkedQueue。 避免嵌套锁:另一种避免死锁的方法是,如果我们已经将锁分配给一个线程,就不要将锁分配给多个线程。因为我们必须避免将锁分配给多个线程。 使用 Thread.join() 方法:如果两个线程无限期地等待对方完成,我们可能会遇到死锁。如果一个线程必须等待另一个线程完成,最好使用 join 并设置您希望等待线程完成的最大时间。 使用锁顺序:始终为每个锁分配一个数字值。在获取具有较高数字值的锁之前,先获取具有较低数字值的锁。 锁超时:我们还可以为线程获取锁指定时间。如果线程未能获取锁,它必须等待特定时间,然后重试获取锁。 28) 什么是临界区?临界区是多线程中的一段代码,必须由任何线程独占修改。临界区受到信号量或互斥锁的保护。在 Java 中,有两种方法可以保护临界区:
29) 什么是数值提升?将较小的数值类型转换为较大的数值类型称为**数值提升**。在这种类型中,byte、char 和 short 值将转换为 int 值。int 值在必要时将转换为 long 值。long 和 float 值在需要时将转换为 double 值。 30) Java 中的 SOLID 原则是什么?在 Java 中,SOLID 原则是一种面向对象的概念,应用于软件结构设计。它由**Robert C. Martin**(也称为**Uncle Bob**)构思。这五项原则改变了面向对象编程的世界,也改变了编写软件的方式。它还确保软件是模块化的,易于理解、调试和重构。 SOLID 首字母缩写代表:
|
我们请求您订阅我们的新闻通讯以获取最新更新。