项目里经常用 String 作为缓存 Key、Map Key 和签名参数,为什么 String 设计成不可变?这对业务有什么实际价值?
我的判断
String 的不可变不是为了“语法好看”,而是让常量池复用、哈希键和跨线程传递都有稳定语义;大量拼接则交给 StringBuilder。
项目里我最在意的是 String 作为值传来传去时不会被别人悄悄改掉。请求参数、配置项、类名和 Map 的 key 都大量使用字符串;如果内容能原地变化,常量池无法安全复用,放进 HashMap 后哈希值也可能变化,多线程共享时还要额外加锁。
final 只表示类不能被继承,真正的不可变来自内部状态不对外暴露,而且 replace、substring、concat 都返回新对象。业务代码因此可以放心缓存 String 的哈希值,也可以直接跨线程传递。
我不会把“不可变”理解成任何场景都用 + 拼接。少量表达式编译器会优化;循环中持续拼接日志或 SQL 时会用 StringBuilder,否则会制造很多短命对象,增加 Young GC。