bigywater.tech
Java · 281

字符串模板设计

字符串模板(STR."\{x}")曾经是预览特性,现在呢?这篇用 JDK 21 与 JDK 27 逐种写法真实编译,确认哪里能用、哪里已经不存在,再看字节码和处理器做了什么,以及不用它时的替代写法。

1 / 4
四种环境里能通过编译的只有 JDK 21 加预览
65535
预览编译出的 class 文件的 minor version
5 种
不依赖预览的替代写法,四种环境结果相同

各环境的编译结果

实测 · 本机执行输出
  STR 基本插值
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:3 + 4 = 7
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character
  表达式里调用方法与三元
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:f1 是
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character
  多行文本块模板
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:hi tom | bye
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character
  FMT 格式化模板
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:3.14    42
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character
  RAW 与 StringTemplate 对象
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:[v=, ] [1] v=1
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character
  自定义 Processor
      JDK 21:编译失败 string templates are a preview feature and are disabled by default.
      JDK 21+预览:HI TOM
      JDK 27:编译失败 illegal escape character
      JDK 27+预览:编译失败 illegal escape character

替代写法

实测 · 本机执行输出
  String.format
      JDK 21:3 + 4 = 7
      JDK 21+预览:3 + 4 = 7
      JDK 27:3 + 4 = 7
      JDK 27+预览:3 + 4 = 7
  formatted
      JDK 21:3 + 4 = 7
      JDK 21+预览:3 + 4 = 7
      JDK 27:3 + 4 = 7
      JDK 27+预览:3 + 4 = 7
  MessageFormat
      JDK 21:3 + 4
      JDK 21+预览:3 + 4
      JDK 27:3 + 4
      JDK 27+预览:3 + 4
  + 拼接
      JDK 21:3 + 4 = 7
      JDK 21+预览:3 + 4 = 7
      JDK 27:3 + 4 = 7
      JDK 27+预览:3 + 4 = 7
  文本块 formatted
      JDK 21:hi tom | bye
      JDK 21+预览:hi tom | bye
      JDK 27:hi tom | bye
      JDK 27+预览:hi tom | bye

字节码与运行

实测 · 本机执行输出
  javap 里的关键行:
    minor version: 65535
    #31 = Utf8 BootstrapMethods
    6: invokedynamic #13, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
    BootstrapMethods:
  JDK 21 预览运行: v=3!
  JDK 21 不带 --enable-preview 运行: Error: LinkageError occurred while loading main class T
  JDK 27 带 --enable-preview 运行 JDK 21 编出的类: Error: LinkageError occurred while loading main class T

自定义处理器

实测 · 本机执行输出
  编译: 0 
  运行输出:
     select * from u where name = ? and age > ?
     [x' OR '1'='1, 30]
     select * from u where name = 'x' OR '1'='1'

分步演示

字符串模板
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12 与 JDK 27;只用到这两个版本
    • 没有验证:JDK 22、23 里该特性的中间形态与被移除的具体版本(只观察到 21 可用、27 不可用)、移除原因、后续替代提案的内容、IDE 对模板的支持、STR 对复杂表达式的字节码形态(只看了最简单的一例)
    京ICP备2026067502号-1京公网安备11010502063487号