bigywater.tech
Java · 279

未命名变量与未命名模式

`_` 让你明确地说「这个值我不关心」:catch 参数、循环变量、lambda 参数、record 组件。它在哪些位置合法、在哪些位置仍然报错?字节码里留下了什么?这篇用三种环境逐段真实编译运行。

3 种环境
JDK 21、JDK 21 加 --enable-preview、JDK 27 的对比结果
case A _, B _
多个未命名绑定可以共用一个分支(有名字的 A p, B q 不行)
0 个
含 _ 的方法在 LocalVariableTable 里的条目数

未命名变量

实测 · 本机执行输出
  try { Integer.parseInt("x"); } catch (NumberFormatException _) { ... }
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:坏数字
      JDK 27:坏数字
  for (var _ : List.of(1, 2, 3)) count++
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:次数 3
      JDK 27:次数 3
  try (var _ = new java.io.StringReader("x")) { ... }
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:资源已打开
      JDK 27:资源已打开
  BiFunction<Integer,Integer,Integer> f = (_, y) -> y
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:10
      JDK 27:10
  int _ = side();(只要副作用)
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:[side] 副作用已执行
      JDK 27:[side] 副作用已执行
  同一作用域里声明两个 _  int _ = 1; int _ = 2;
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:两个 _ 都通过
      JDK 27:两个 _ 都通过
  引用 _  int _ = 1; System.out.println(_);
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:编译失败 as of release 21, the underscore keyword '_' is only allowed to declare
      JDK 27:编译失败 underscore not allowed here
  _ 作为字段名/方法名(class X { int _; })
      JDK 21:编译失败 as of release 9, '_' is a keyword, and may not be used as an identifier
      JDK 21+预览:编译失败 as of release 21, the underscore keyword '_' is only allowed to declare
      JDK 27:编译失败 underscore not allowed here
  Map.forEach 里 (k, _) -> …
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:ab
      JDK 27:ab

未命名模式

实测 · 本机执行输出
  o instanceof Point(int x, _)  / Point(_, var y)
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:x=3 y=4
      JDK 27:x=3 y=4
  case Box(_) -> "盒子"(单独的 _ 模式)
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:盒子
      JDK 27:盒子
  case A _, B _ -> "ab"(多个未命名绑定的模式)
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:ab
      JDK 27:ab
  case A _ when side() > 0 -> …(未命名 + 守卫)
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:[side]A+守卫
      JDK 27:[side]A+守卫
  case A(_) / case B(_) 嵌套
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:A
      JDK 27:A
  case A p, B q(逗号分隔、有名字的绑定)
      JDK 21:编译失败 illegal fall-through from a pattern
      JDK 21+预览:编译失败 illegal fall-through from a pattern
      JDK 27:编译失败 illegal fall-through from a pattern
  o instanceof _(裸 _ 不是合法的类型模式)
      JDK 21:编译失败 as of release 9, '_' is a keyword, and may not be used as an identifier
      JDK 21+预览:编译失败 as of release 21, the underscore keyword '_' is only allowed to declare
      JDK 27:编译失败 underscore not allowed here
  var _ = ...; 类型是 var 的 _
      JDK 21:编译失败 unnamed variables are a preview feature and are disabled by default.
      JDK 21+预览:var _ 通过
      JDK 27:var _ 通过

字节码与历史

实测 · 本机执行输出
  JDK 27 编译(--enable-preview -g): 0 
  javap -l 的 LocalVariableTable: (没有任何局部变量条目)
  JDK 21 --release 8 编译 int _ = 1: 通过(带 warning) warning: [options] source value 8 is obsolete and will be removed in a future release | warning: [options] target value 8 is obsolete and will be removed in a f
  JDK 21 --release 9 编译 int _ = 1: 失败 <实验目录> error: unnamed variables 
  JDK 21 --release 21 编译 int _ = 1: 失败 <实验目录> error: unnamed variables 

分步演示

未命名变量与未命名模式
本步的对象

    本文用到的工具与边界

    • 本机 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 22(特性转正的版本)的实际行为、_ 与注解、泛型方法的组合、IDE 对未使用变量的提示、模式 switch 穷尽性与 _ 的交互的所有边界、其它语言(Kotlin 等)的对应特性
    京ICP备2026067502号-1京公网安备11010502063487号