java驼峰转下划线的关键是准确识别大小写边界,尤其处理连续大写字母(如xml、http),推荐使用guava的caseformat或手写状态机逻辑,避免正则误切。

Java 中将驼峰命名(如 userName、XMLHttpRequest)转为下划线命名(如 user_name、xml_http_request)的关键是:**识别大小写字母边界,尤其是连续大写字母的处理**。标准做法不是简单地在每个大写字母前加下划线,而是要区分单词边界(如 iPhone → i_phone,URLParser → url_parser),同时保持首尾不带下划线、全小写输出。
基础正则替换(适用于常规驼峰)
对大多数常见驼峰(如 firstName、myXMLData),可用两步正则处理:
- 先匹配「小写字母+大写字母」→ 在中间插入下划线,如
myName→my_Name - 再匹配「大写字母+大写字母+小写字母」→ 在第一个大写后插入下划线,如
XMLParser→XML_Parser,再配合第一步变成x_m_l_parser?不对——这会出错。所以更稳妥的是用「前瞻+后顾」组合判断边界
推荐单次正则方案(JDK 7+):
String underscore = camelCase.replaceAll("([a-z])([A-Z])", "$1_$2")
.replaceAll("([A-Z])([A-Z][a-z])", "$1_$2")
.toLowerCase();
说明:
• 第一个 replaceAll 处理 aB → a_B(如 userType → user_Type)
• 第二个处理 ABc → A_Bc(如 XMLParser → XM_LParser,再经上一步变 xml_parser)
• 最后统一转小写
处理特殊缩略词(如 HTTP、ID、URL)
纯正则容易把 userId 错切成 u_ser_id 或 user_i_d。更健壮的方式是预定义常见缩略词表,或使用成熟工具类:
- Apache Commons Lang 的
StringUtils.uncapitalize(StringUtils.replacePattern(str, "([A-Z])", "_$1"))不够智能,建议用CaseUtils.toCamelCase()的逆向思路 - 实际项目中推荐直接用
com.google.common.base.CaseFormat(Guava):
String underscore = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "XmlHttpRequest"); // 结果:"xml_http_request"
它内置了对缩略词的识别逻辑(如 XML、HTTP、ID 会被整体视为一个单词),无需手动维护规则。
手写健壮解析(无第三方依赖时)
若不能引入 Guava,可参考 Spring Framework 的 org.springframework.util.StringUtils#camelCaseToUnderscore 思路,核心逻辑是遍历字符,按状态机判断是否插入下划线:
- 记录前一字符是否为大写、是否为字母、是否刚插入过下划线
- 遇到大写字母时,检查前一个是小写(
aB)、或前一个是大写但后一个是小写(ABc)→ 此时才加下划线 - 跳过开头和结尾的下划线,最后转小写
示例片段(简化版):
StringBuilder result = new StringBuilder();
for (int i = 0; i 0 && !Character.isUpperCase(str.charAt(i-1))
|| (i
注意边界情况
以下输入需验证你的方法是否正确处理:
-
iPhone→i_phone(不是iphone或i_phone✅) -
parseXML→parse_xml(不是parse_x_m_l) -
URL→url(单个缩略词全转小写) -
MyIDGenerator→my_id_generator(不是my_i_d_generator)
Guava 的 CaseFormat 和 Spring 的实现均能正确覆盖这些场景;自研正则若未分两步或未加后顾条件,大概率会出错。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











