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

深入理解Java中的String

前言

在Java中,String类是一个非常重要的内置类,用于处理字符串数据。字符串是不可变的(immutable),这意味着一旦创建,字符串的内容不能被修改。作为Java中最为基础和常用的类之一,String类在内存管理、线程安全、性能优化等方面都有着独特的设计和实现。本文将详细介绍Java中String类的特点、用途、主要方法以及常见用法,并通过代码示例展示如何在Java中创建、操作和使用String类。

1. String类的特点

1.1 不可变性

String对象一旦创建,其内容就不能被更改。这种不可变性是通过final关键字修饰字符数组value来实现的。String类中没有提供修改字符数组的方法,任何对字符串的修改操作(如拼接、替换等)都会创建一个新的String对象。

String str1 = "Hello";
String str2 = str1.concat(" World"); // 创建一个新的字符串对象"Hello World"
System.out.println(str1); // 输出: Hello
System.out.println(str2); // 输出: Hello World

不可变性带来了多个好处:

  • 安全性:在多线程环境中,多个线程可以安全地共享同一个字符串对象,而不用担心数据被修改。
  • 内存效率:不可变字符串可以被共享。当在常量池中创建一个字符串字面量时,后续对同一内容的引用会直接指向常量池中的对象,而不是创建新的对象,从而减少了内存消耗。
  • 哈希码缓存:由于字符串不可变,它们的哈希码只计算一次,并可以被缓存。这使得字符串在作为哈希表的键时更加高效,因为不需要在每次查找时重新计算哈希值。

1.2 字符串常量池

字符串常量池是Java中一个特殊的内存区域,用于存储字符串字面量和一些常量字符串。当使用字面量方式创建String对象时,JVM会首先检查字符串常量池中是否已经存在相同内容的字符串对象。如果存在,则直接返回常量池中该字符串对象的引用;如果不存在,则在常量池中创建一个新的字符串对象,并返回其引用。

String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // 输出: true,str1和str2引用的是同一个字符串对象

通过intern()方法,可以手动将一个String对象放入字符串常量池中。

String str1 = new String("Hello");
String str2 = str1.intern();
String str3 = "Hello";
System.out.println(str2 == str3); // 输出: true,str2和str3引用的是同一个字符串对象

1.3 内存结构

String对象在内存中的存储结构主要包括字符数组value、哈希码hash以及偏移量offset(在JDK 9及以后版本中,如果字符串内容都在Latin-1字符集内,则使用byte数组存储,并结合编码标识来区分)。

  • 字符数组value:用于存储字符串的字符序列。在JDK 9之前,使用的是UTF-16编码的字符数组;在JDK 9及以后版本中,如果字符串内容都在Latin-1字符集内,则使用byte数组存储。
  • 哈希码hash:用于缓存字符串的哈希码,以避免在每次调用hashCode()方法时重新计算。
  • 偏移量offset(在JDK 9及以后版本中):用于标识字符串在byte数组中的起始位置(如果字符串使用byte数组存储)。

1.4 JDK版本更新对String类的影响

随着JDK版本的更新,String类的底层设计和优化也在不断发展。

  • JDK 6:字符串常量池位于永久代(方法区)中,存储的是对象本身。
  • JDK 7:将常量池从永久代移到了堆内存中,存储的是对象的引用。
  • JDK 8:引入了元空间(Metaspace)来取代永久代,优化了字符串的创建和intern()方法的行为。
  • JDK 9:对String类进行了重大的底层优化,改用byte数组存储字符串数据(如果字符串内容都在Latin-1字符集内),并引入了coder字段和COMPACT_STRINGS属性来控制字符串的紧凑存储功能。

2. String类的用途

2.1 表示文本数据

字符串是计算机科学中用来表示文本数据的标准方式。在Java中,字符串常用于表示用户的姓名、地址等个人信息,以及程序中的各种文本信息。

2.2 处理文本数据

Java提供了丰富的内置函数和方法,使开发者能够轻松地进行文本数据的处理。例如,可以使用String类的各种方法来查找子字符串、替换字符、分割字符串等。

2.3 内存管理和性能优化

通过字符串常量池和不可变性设计,String类在内存管理和性能优化方面表现出色。它减少了内存中的重复字符串存储,提高了内存利用率和访问效率,并允许JVM对字符串进行缓存和重用,减少了创建新对象的开销。

3. String类的主要方法

3.1 创建字符串

3.1.1 直接赋值

String str = "Hello, World!";

这种方式创建的字符串对象会被放入字符串常量池中。

3.1.2 使用new关键字

String str = new String("Hello, World!");

这种方式会在堆内存中创建一个新的String对象,而不会放入字符串常量池中(除非通过intern()方法手动放入)。

3.1.3 字符数组转String

char[] array = {'a', 'b', 'c'};
String str = new String(array);

3.2 字符串比较

3.2.1 == 比较

String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");System.out.println(str1 == str2); // 输出: true,str1和str2引用的是同一个字符串对象
System.out.println(str1 == str3); // 输出: false,str1和str3引用的是不同的字符串对象

== 比较的是字符串对象的引用是否相同。

3.2.2 equals方法

System.out.println(str1.equals(str3)); // 输出: true,str1和str3的内容相同

equals方法比较的是字符串对象的内容是否相同。

3.2.3 compareTo方法

String str4 = "World";
System.out.println(str1.compareTo(str4)); // 输出: -11,按照字典顺序,"Hello"小于"World"

compareTo方法按字典顺序比较两个字符串的大小关系,返回值为int类型。

3.2.4 compareToIgnoreCase方法

System.out.println(str1.compareToIgnoreCase(str4)); // 输出: -11,忽略大小写比较

compareToIgnoreCase方法与compareTo方法类似,但在比较时忽略字母大小写。

3.3 获取长度

String str = "Hello, World!";
int length = str.length(); // 返回字符串的长度
System.out.println(length); // 输出: 13

3.4 字符串查找

3.4.1 charAt方法

char ch = str.charAt(7); // 返回指定索引位置上的字符
System.out.println(ch); // 输出: W

charAt方法返回指定索引位置上的字符,索引范围从0开始。

3.4.2 indexOf方法

int index = str.indexOf("World"); // 返回指定子字符串第一次出现的位置
System.out.println(index); // 输出: 7index = str.indexOf("Java", 8); // 从指定索引开始查找
System.out.println(index); // 输出: -1,未找到

indexOf方法返回指定子字符串第一次出现的位置,如果未找到则返回-1。

3.4.3 lastIndexOf方法

int lastIndex = str.lastIndexOf("o"); // 返回指定字符最后一次出现的位置
System.out.println(lastIndex); // 输出: 8lastIndex = str.lastIndexOf("o", 7); // 从指定索引开始反向搜索
System.out.println(lastIndex); // 输出: 4

lastIndexOf方法返回指定字符或子字符串最后一次出现的位置,如果未找到则返回-1。

3.4.4 contains方法

boolean containsHello = str.contains("Hello"); // 判断字符串是否包含指定的字符序列
System.out.println(containsHello); // 输出: true

contains方法用于判断字符串是否包含指定的字符序列。

3.5 子字符串

3.5.1 substring方法

String subStr = str.substring(7, 12); // 返回从beginIndex开始到endIndex-1的子字符串
System.out.println(subStr); // 输出: World

substring方法返回从beginIndex开始到endIndex-1的子字符串。

3.6 字符串替换

3.6.1 replace方法

String replacedStr = str.replace("World", "Java"); // 替换字符串中的字符
System.out.println(replacedStr); // 输出: Hello, Java!

replace方法用于替换字符串中的字符或子字符串。

3.6.2 replaceAll方法

String replacedAllStr = str.replaceAll("o", "0"); // 使用正则表达式替换字符串中的内容
System.out.println(replacedAllStr); // 输出: Hell0, W0rld!

replaceAll方法使用正则表达式替换字符串中的所有匹配项。

3.6.3 replaceFirst方法

String replacedFirstStr = str.replaceFirst("o", "0"); // 替换字符串中的第一个匹配项
System.out.println(replacedFirstStr); // 输出: Hello, W0rld!

replaceFirst方法替换字符串中的第一个匹配项。

3.7 大小写转换

3.7.1 toLowerCase方法

String lowerStr = str.toLowerCase(); // 将字符串转换为小写
System.out.println(lowerStr); // 输出: hello, world!

toLowerCase方法将字符串转换为小写。

3.7.2 toUpperCase方法

String upperStr = str.toUpperCase(); // 将字符串转换为大写
System.out.println(upperStr); // 输出: HELLO, WORLD!

toUpperCase方法将字符串转换为大写。

3.8 去除字符串首尾空格

String trimmedStr = str.trim(); // 去除字符串两端的空白字符
System.out.println(trimmedStr); // 输出: Hello, World!(假设原字符串两端没有空格)

trim方法用于去除字符串两端的空白字符(包括空格、制表符、换行符等)。

3.9 字符串拆分

String[] splitStrs = str.split(", "); // 根据正则表达式拆分字符串
for (String s : splitStrs) {System.out.println(s);
}
// 输出:
// Hello
// World!

split方法根据给定的正则表达式拆分字符串,并返回一个字符串数组。

3.10 字符串连接

3.10.1 使用+操作符

String concatenatedStr = "Hello" + " " + "World!"; // 使用+操作符连接字符串
System.out.println(concatenatedStr); // 输出: Hello World!

在编译时,Java会将多个字符串字面量的拼接优化为一个StringBuilder的append操作。

3.10.2 使用StringBuilder或StringBuffer

StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World!");
String concatenatedStr = sb.toString();
System.out.println(concatenatedStr); // 输出: Hello World!

StringBuilder和StringBuffer都提供了可变字符串的操作,但StringBuilder是非线程安全的,而StringBuffer是线程安全的。在单线程环境中,建议使用StringBuilder以提高性能。

3.11 其他常用方法

3.11.1 startsWith方法

boolean startsWithHello = str.startsWith("Hello"); // 判断字符串是否以指定的前缀开始
System.out.println(startsWithHello); // 输出: true

startsWith方法用于判断字符串是否以指定的前缀开始。

3.11.2 endsWith方法

boolean endsWithExclamation = str.endsWith("!"); // 判断字符串是否以指定的后缀结束
System.out.println(endsWithExclamation); // 输出: true

endsWith方法用于判断字符串是否以指定的后缀结束。

3.11.3 toCharArray方法

char[] charArray = str.toCharArray(); // 将字符串转换为字符数组
for (char c : charArray) {System.out.print(c);
}
// 输出: Hello, World!

toCharArray方法将字符串转换为字符数组。

3.11.4 split(String regex, int limit)方法

String[] splitStrsWithLimit = str.split(", ", 2); // 根据正则表达式拆分字符串,并限制拆分次数
for (String s : splitStrsWithLimit) {System.out.println(s);
}
// 输出:
// Hello
// World!

split(String regex, int limit)方法根据给定的正则表达式拆分字符串,并限制拆分的次数。

4. String类的常见用法

4.1 字符串拼接

在Java中,字符串拼接是一个常见的操作。由于String的不可变性,直接使用+操作符进行字符串拼接可能会导致性能问题(特别是在循环中多次拼接字符串时)。因此,建议使用StringBuilder或StringBuffer来进行字符串拼接。

// 使用+操作符进行字符串拼接(不推荐在循环中使用)
String result = "";
for (int i = 0; i < 1000; i++) {result += "Hello ";
}
System.out.println(result);// 使用StringBuilder进行字符串拼接(推荐)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {sb.append("Hello ");
}
String resultWithStringBuilder = sb.toString();
System.out.println(resultWithStringBuilder);

4.2 字符串比较

在Java中,字符串比较通常使用equals方法而不是 ==操作符。因为==操作符比较的是字符串对象的引用是否相同,而equals方法比较的是字符串对象的内容是否相同。

String str1 = "Hello";
String str2 = new String("Hello");System.out.println(str1 == str2); // 输出: false,str1和str2引用的是不同的字符串对象
System.out.println(str1.equals(str2)); // 输出: true,str1和str2的内容相同

4.3 字符串查找和替换

在文本处理中,经常需要查找子字符串或替换字符串中的某些字符。String类提供了丰富的方法来支持这些操作。

String text = "Hello, welcome to the world of Java!";// 查找子字符串
int index = text.indexOf("welcome");
System.out.println("Index of 'welcome': " + index); // 输出: 7// 替换字符串中的字符
String replacedText = text.replace("Java", "Programming");
System.out.println(replacedText); // 输出: Hello, welcome to the world of Programming!

4.4 字符串拆分

在处理CSV文件或解析复杂字符串时,经常需要将字符串拆分为多个部分。String类的split方法提供了方便的方式来实现这一点。

String csvLine = "name,age,city";
String[] fields = csvLine.split(",");for (String field : fields) {System.out.println(field);
}
// 输出:
// name
// age
// city

4.5 字符串格式化

在输出格式化字符串时,可以使用String.format方法或Formatter类。

String name = "Alice";
int age = 30;
String formattedString = String.format("Name: %s, Age: %d", name, age);
System.out.println(formattedString); // 输出: Name: Alice, Age: 30

总结

Java中的String类是一个重要的内置类,用于处理字符串数据。其特点包括不可变性、字符串常量池、特定的内存结构以及随JDK版本更新的优化。String类广泛用于表示和处理文本数据,并在内存管理和性能优化方面表现出色。主要方法包括创建字符串、字符串比较、获取长度、字符串查找、子字符串操作、字符串替换、大小写转换、去除首尾空格、字符串拆分和连接等。常见用法涉及字符串拼接、比较、查找和替换、拆分以及格式化。通过合理使用String类的方法,可以有效处理文本数据并优化程序性能。

相关文章:

深入理解Java中的String

前言 在Java中&#xff0c;String类是一个非常重要的内置类&#xff0c;用于处理字符串数据。字符串是不可变的&#xff08;immutable&#xff09;&#xff0c;这意味着一旦创建&#xff0c;字符串的内容不能被修改。作为Java中最为基础和常用的类之一&#xff0c;String类在内…...

洛谷 P1734 最大约数和 C语言

P1734 最大约数和 - 洛谷 | 计算机科学教育新生态 题目描述 选取和不超过 S 的若干个不同的正整数&#xff0c;使得所有数的约数&#xff08;不含它本身&#xff09;之和最大。 输入格式 输入一个正整数 S。 输出格式 输出最大的约数之和。 输入输出样例 输入 #1复制 …...

Golang 执行流程分析

文章目录 1. 编译和运行2. 编译和运行说明 1. 编译和运行 如果是对源码编译后&#xff0c;再执行&#xff0c;Go的执行流程如下图 如果我们是对源码直接 执行 go run 源码&#xff0c;Go的执行流程如下图 两种执行流程的方式区别 如果先编译生成了可执行文件&#xff0c;那么…...

python学opencv|读取图像(五十一)使用修改图像像素点上BGR值实现图像覆盖效果

【1】引言 前序学习了图像的得加方法&#xff0c;包括使用add()函数直接叠加BGR值、使用bitwise()函数对BGR值进行按位计算叠加和使用addWeighted()函数实现图像加权叠加至少三种方法。文章链接包括且不限于&#xff1a; python学opencv|读取图像&#xff08;四十二&#xff…...

Flask数据的增删改查(CRUD)_flask删除数据自动更新

查询年龄小于17的学生信息 Student.query.filter(Student.s_age < 17) students Student.query.filter(Student.s_age.__lt__(17))模糊查询&#xff0c;使用like&#xff0c;查询姓名中第二位为花的学生信息 like ‘_花%’,_代表必须有一个数据&#xff0c;%任何数据 st…...

kamailio-ACC模块介绍【kamailio6.0. X】

Acc 模块 作者 Jiri Kuthan iptel.org jiriiptel.org Bogdan-Andrei Iancu Voice Sistem SRL bogdanvoice-system.ro Ramona-Elena Modroiu rosdev.ro ramonarosdev.ro 编辑 Bogdan-Andrei Iancu Voice Sistem SRL bogdanvoice-system.ro Sven Knoblich 1&1 Internet …...

数据库对象

数据库对象 数据库对象是构成数据库结构的基本单位&#xff0c;它们定义了数据库存储的数据类型、数据的组织方式以及数据之间的关系。在数据库中&#xff0c;对象可以包括表&#xff0c;视图&#xff0c;索引&#xff0c;触发器&#xff0c;存储过程&#xff0c;函数等多种类…...

EtherCAT主站IGH-- 27 -- IGH之globals.h文件解析

EtherCAT主站IGH-- 27 -- IGH之globals.h文件解析 0 预览一 该文件功能宏定义数据结构打印宏三 h文件翻译四 c文件翻译该文档修改记录:总结0 预览 一 该文件功能 该文件包含了一些全局定义和宏,用于 IgH EtherCAT 主站(EtherCAT Master)的实现。包括了一些超时设定、宏定义…...

2025多目标优化创新路径汇总

多目标优化是当下非常热门且有前景的方向&#xff01;作为AI领域的核心技术之一&#xff0c;其专注于解决多个相互冲突的目标的协同优化问题&#xff0c;核心理念是寻找一组“不完美但均衡”的“帕累托最优解”。在实际中&#xff0c;几乎处处都有它的身影。 但随着需求场景的…...

15JavaWeb——Maven高级篇

Maven高级 Web开发讲解完毕之后&#xff0c;我们再来学习Maven高级。其实在前面的课程当中&#xff0c;我们已经学习了Maven。 我们讲到 Maven 是一款构建和管理 Java 项目的工具。经过前面 10 多天 web 开发的学习&#xff0c;相信大家对于 Maven 这款工具的基本使用应该没什…...

使用Ollama本地化部署DeepSeek

1、Ollama 简介 Ollama 是一个开源的本地化大模型部署工具&#xff0c;旨在简化大型语言模型&#xff08;LLM&#xff09;的安装、运行和管理。它支持多种模型架构&#xff0c;并提供与 OpenAI 兼容的 API 接口&#xff0c;适合开发者和企业快速搭建私有化 AI 服务。 Ollama …...

蓝桥杯刷题DAY1:前缀和

所谓刷题&#xff0c;讲究的就是细心 帕鲁服务器崩坏【算法赛】 “那个帕鲁我已经观察你很久了&#xff0c;我对你是有些失望的&#xff0c;进了这个营地&#xff0c;不是把事情做好就可以的&#xff0c;你需要有体系化思考的能力。” 《幻兽帕鲁》火遍全网&#xff0c;成为…...

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之用户注册

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;项目基本介绍 &#x1f6a6;项…...

MINIRAG: TOWARDS EXTREMELY SIMPLE RETRIEVAL-AUGMENTED GENERATION论文翻译

感谢阅读 注意不含评估以后的翻译原论文地址标题以及摘要介绍部分MiniRAG 框架2.1 HETEROGENEOUS GRAPH INDEXING WITH SMALL LANGUAGE MODELS2.2 LIGHTWEIGHT GRAPH-BASED KNOWLEDGE RETRIEVAL2.2.1 QUERY SEMANTIC MAPPING2.2.2 TOPOLOGY-ENHANCED GRAPH RETRIEVAL 注意不含评…...

微服务入门(go)

微服务入门&#xff08;go&#xff09; 和单体服务对比&#xff1a;里面的服务仅仅用于某个特定的业务 一、领域驱动设计&#xff08;DDD&#xff09; 基本概念 领域和子域 领域&#xff1a;有范围的界限&#xff08;边界&#xff09; 子域&#xff1a;划分的小范围 核心域…...

Baklib揭示内容中台实施最佳实践的策略与实战经验

内容概要 在当前数字化转型的浪潮中&#xff0c;内容中台的概念日益受到关注。它不再仅仅是一个内容管理系统&#xff0c;而是企业提升运营效率与灵活应对市场变化的重要支撑平台。内容中台的实施离不开最佳实践的指导&#xff0c;这些实践为企业在建设高效内容中台时提供了宝…...

C++11新特性之lambda表达式

1.介绍 C11引入了lambda表达式。lambda表达式提供一种简洁的方式来定义匿名函数对象&#xff0c;使得在需要临时定义一个函数时非常方便。 2.lambda表达式用法 lambda表达式的基本用法为&#xff1a; [捕获列表]&#xff08;参数列表&#xff09;->返回类型 { 函数体 …...

洛谷 P10289 [GESP样题 八级] 小杨的旅游 C++ 完整题解

一、题目链接 P10289 [GESP样题 八级] 小杨的旅游 - 洛谷 二、题目大意 n个节点之间有n - 1条边&#xff0c;其中k个节点是传送门&#xff0c;任意两个传送门之间可以 以0单位地时间相互到达。问从u到v至少需要多少时间&#xff1f; 三、解题思路 输入不必多讲。 cin >> …...

使用 Tauri 2 + Next.js 开发跨平台桌面应用实践:Singbox GUI 实践

Singbox GUI 实践 最近用 Tauri Next.js 做了个项目 - Singbox GUI&#xff0c;是个给 sing-box 用的图形界面工具。支持 Windows、Linux 和 macOS。作为第一次接触这两个框架的新手&#xff0c;感觉收获还蛮多的&#xff0c;今天来分享下开发过程中的一些经验~ 为啥要做这个…...

JWT入门

一、初识JWT&#xff1a;新时代的身份认证方案 在分布式系统成为主流的今天&#xff0c;传统的Session认证方式逐渐显露出局限性。JWT&#xff08;JSON Web Token&#xff09;作为现代Web开发的认证新标准&#xff0c;凭借其无状态、跨域友好和安全性等特性&#xff0c;正在成为…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...