substring(0, 1).toUpperCase() 易抛 StringIndexOutOfBoundsException,因空字符串或 null 时 substring 不容越界;需先判空且注意 toUpperCase() 作用于整串、非首字母,正确做法是结合 substring(1).toLowerCase() 或用 Character.toUpperCase() + charAt() 避免对象开销,并显式指定 Locale 防国际化问题。

为什么 substring(0, 1).toUpperCase() 容易抛 StringIndexOutOfBoundsException
空字符串或 null 输入时,substring(0, 1) 直接崩溃——这是最常踩的坑。Java 的 substring 不容忍越界起始索引,哪怕只是想取首字符。
实际场景比如处理用户输入、JSON 字段解析、日志字段清洗,都可能遇到空值。
- 必须先判空:
str != null && !str.isEmpty() - 更安全写法是用
str.length() > 0,避免isEmpty()在低版本 JDK 的兼容性问题 - 如果业务允许默认值,可提前 return “” 或 “A” 类占位符,别让异常穿透到上层
只用 toUpperCase() 会把整个字符串变大写,不是首字母大写
toUpperCase() 作用于整个字符串,不是“首字母”操作。常见误用是写成 str.toUpperCase().substring(0, 1) + str.substring(1),结果后半截没转小写,大小写混乱。
典型错误现象:输入 "java" → 得到 "JAVAava"(因为 str.substring(1) 还是 "ava",没做小写处理)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 正确组合是:
str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase() - 但要注意:中文、数字、符号在
toLowerCase()中不变,所以对混合字符串安全;但若原串含已大写的后续字母(如"iPhone"),toLowerCase()会让它变成"iphone",丢失原有 casing 逻辑 - 如需保留非首字母的原始大小写(如驼峰名),就不能简单用
substring(1).toLowerCase()
推荐用 Character.toUpperCase() + String.valueOf() 避免子串开销
频繁调用 substring() 会产生新字符串对象,在循环或高吞吐场景下有 GC 压力。JDK 7+ 虽优化了 substring 底层引用,但语义上仍是新对象。
更轻量的做法是直接操作首字符:
if (str != null && !str.isEmpty()) {
char first = Character.toUpperCase(str.charAt(0));
return String.valueOf(first) + str.substring(1);
}
-
charAt(0)比substring(0, 1)少一次对象分配 -
Character.toUpperCase()支持 Unicode(比如德语 ß、土耳其语 I),比字符串级toUpperCase()更精准 - 注意:
String.valueOf(char)比new String(new char[]{c})快且省内存
国际化场景下,toUpperCase(Locale) 不能省
不带 Locale 参数的 toUpperCase() 依赖 JVM 默认区域设置,同一段代码在土耳其服务器上运行,"i".toUpperCase() 会变成 "İ"(带点大写 I),而非 "I",导致前端匹配失败或 SQL 查询异常。
- 始终显式传
Locale.ENGLISH或业务对应 locale:str.substring(0, 1).toUpperCase(Locale.ENGLISH) - 如果处理多语言用户名,应使用用户请求头中的
Accept-Language对应 locale,而不是硬编码 -
Character.toUpperCase(int codePoint, Locale)是 Java 12+ 才支持的重载,老版本只能靠字符串级方法兜底

















