JEP 草案:字符串模板(最终版)
Java 语言核心中的新字符串模板提案正因其以安全为导向的设计而获得赞誉,也因其不寻常且冗长的语法(`STR."...\{x}..."`)而受到批评。支持者认为,模板处理器和 `\{}` 语法能够通过引导开发者远离原始字符串插值和注入风险,更安全地构造 SQL、HTML、JSON 以及其他结构化输出。批评者则反驳说,这一特性把其他语言用更简单插值就能解决的问题复杂化了,并质疑这种易用性上的取舍以及向后兼容性的理由是否值得增加如此多的复杂度。
整体反响
- 许多人欢迎 Java 终于有了字符串模板,并认为它们非常强大,尤其是在结合自定义处理器和类型安全 API(HTML、SQL、JSON)时。
- 相当一部分评论认为这一设计“丑陋”、“过度工程化”,而且与其他语言(Kotlin、Python、JS、C# 等)相比过于冗长。
- 一些人认为,尽管设计上有其理由,但常见场景(简单插值)如今比其他语言以及现有 Java 习惯用法更糟。
语法:STR."..." 和 \{...}
- 对
STR.接收者加上\{expr}语法的批评非常强烈:视觉上很吵,因为\传统上表示转义,而且很容易被误读为转义{,而不是开始插值。 - 也有人为它辩护,认为这与 Java 保持一致:
\本来就意味着“字面量中的特殊解释”;\{以前是非法的,因此当遗漏处理器时可以给出有帮助的编译期错误。 - 有人认为,既然无论如何都需要像
STR这样的处理器,那么为了向后兼容而使用\{}是多余的;本可以使用${}或{}。 - 反对意见是:
$在现有 Java 模板生态中被广泛使用,把它设为特殊符号会带来转义和迁移成本。
安全性与设计目标
- 支持者强调,这个特性并不只是为了做字符串插值;它被设计出来是为了通过以下方式对抗注入漏洞:
- 让模板表达式成为类型化处理器上的方法调用(例如
SQL."..."、HTML."...")。 - 允许库拒绝普通
StringAPI,只接受由处理器生成的安全类型。
- 让模板表达式成为类型化处理器上的方法调用(例如
- 批评者回应说,在实践中大多数开发者只会用
STR/FMT来做插值,并继续把不安全的 SQL/HTML 作为字符串来写。
自定义模板处理器 / DSL
- 有些人认为用户自定义处理器是一个重大胜利,类似于 JavaScript 的标签模板和 Scala 的插值器,能够实现安全、面向领域的构建器(SQL、HTML、JSON、XML)。
- 另一些人担心会涌现大量临时性的迷你 DSL,增加认知负担和维护风险。
- 少数人指出,Scala 和 JS 中类似的特性并没有明显导致大规模滥用。
性能与工具链
- 有人担心分配开销(值列表)以及对 MethodHandle 特化的依赖;回应指出,特化并不只限于内建处理器。
- 一些人认为所谓“没有额外工具成本”的说法被夸大了,因为解析器/IDE 仍然必须处理新的表达式形式。