bigywater.tech
Java · 278

原始类型模式匹配

原始类型模式让 instanceof 与 switch 可以直接匹配 int、long、double 等原始类型,并把「值能不能精确转换」变成一个测试。这篇在 JDK 21 与 27 上逐段真实编译运行,看它现在处于什么状态、每种转换的边界在哪里。

8 / 8
JDK 21 上编译失败的段数;JDK 27 加 --enable-preview 后全部通过
16777216 / 16777217
int 精确转成 float 的边界(前者可以,后者不行)
预览
到 JDK 27 这个特性的状态

三种环境的结果

实测 · 本机执行输出
  Object o = 42; if (o instanceof int i) println(i)
      JDK 21:编译失败 unexpected type
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:int 42
  int x = 300; if (x instanceof byte b) ...(int 能否精确转成 byte)
      JDK 21:编译失败 unexpected type
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:不能精确转成 byte
  int x = 100; if (x instanceof byte b) ...
      JDK 21:编译失败 unexpected type
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:byte 100
  long l = 5L; switch (l) { case 5L -> ... }(switch 长整型)
      JDK 21:编译失败 selector type long is not allowed
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:five
  boolean b = true; switch (b) { case true -> ... }
      JDK 21:编译失败 selector type boolean is not allowed
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:T
  double d = 1.5; switch (d) { case double x when x > 1 -> ... }
      JDK 21:编译失败 selector type double is not allowed
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:gt1
  Integer boxed = 7; switch (boxed) { case int i when i > 5 -> ... }
      JDK 21:编译失败 unexpected type
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:big
  int x = 3; switch (x) { case int i when i > 2 -> ... }
      JDK 21:编译失败 unexpected type
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:gt2

精确转换的边界

实测 · 本机执行输出
  float f = 16777217; int→float 精确吗
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:int 16777217 不能精确转成 float
  int x = 16777216; instanceof float
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:float 1.6777216E7
  long l = Integer.MAX_VALUE + 1L; instanceof int
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:long 超出 int 范围
  double d = 0.1; instanceof float
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:0.1 不能精确转成 float
  double d = 0.5; instanceof float
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:float 0.5
  char c = 65; int i = c; i instanceof char
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:char A
  int i = -1; instanceof char(范围外)
      JDK 27:编译失败 primitive patterns are a preview feature and are disabled by default.
      JDK 27+preview:-1 不是合法的 char

特性状态

实测 · 本机执行输出
  JDK 21: javac 21.0.12.1
  JDK 27: javac 27
  JDK 27 不加 --enable-preview 编译 instanceof int: <jtmp>/j138m/T.java:1: error: primitive patterns are a preview feature and are disabled by default. ;  (use --enable-preview to enable primitive patterns)
  JDK 27 加 --enable-preview --release 27: 编译并运行: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 27 的行为随版本变化,以编译当时为准
    • 没有验证:JDK 27 之外的预览版本(23、24、25、26)之间的差异、模式 switch 里原始类型的穷尽性规则的全部细节、字节码里原始类型模式的实现(invokedynamic 或比较指令)、与装箱类型的混合 switch 的性能、该特性最终转正后的最终语法
    京ICP备2026067502号-1京公网安备11010502063487号