咨询JEP 405中Java模式匹配表达式求值代码的逻辑与变量来源
Java记录模式匹配表达式求值代码解释
这段代码是基于Java预览特性「记录模式匹配」实现的算术表达式递归求值函数,核心作用是把结构化的算术表达式树计算出最终整数结果。
核心疑问解答:left/right的来源
你在case里看到的left、right变量是模式匹配对记录类型自动解构得到的,确实和入参n直接相关:
Expr是所有表达式类型的公共父类/密封接口,AddExpr、MulExpr都是实现了Expr的记录(Record)类,这两个类定义时就声明了两个Expr类型的成员变量,分别命名为left和right。当你写case AddExpr(Expr left, Expr right)的时候,程序首先会判断入参n是不是AddExpr的实例,如果是,就会自动把这个实例的两个成员变量提取出来,赋值给你声明的left和right变量,不需要手动调用getter或者强转类型。
代码逐行解释
// 输入参数是抽象表达式节点n,返回求值后的整数结果 int eval(Expr n) { return switch(n) { // 如果n是整数常量表达式IntExpr,解构出它存储的整数值i,直接返回i case IntExpr(int i) -> i; // 如果n是取反表达式NegExpr,解构出它存储的子表达式n,递归求值后取反返回 case NegExpr(Expr n) -> -eval(n); // 如果n是加法表达式AddExpr,解构出左右操作数表达式,分别递归求值后相加 case AddExpr(Expr left, Expr right) -> eval(left) + eval(right); // 如果n是乘法表达式MulExpr,解构出左右操作数表达式,分别递归求值后相乘 case MulExpr(Expr left, Expr right) -> eval(left) * eval(right); // 匹配到未定义的表达式类型时抛出异常 default -> throw new IllegalArgumentException(n); }; }
多语言重写参考思路
这种实现本质是代数数据类型(ADT)+ 模式匹配的经典写法,不同语言对应实现方式如下:
- C语言:用带标签的union实现ADT,先定义枚举标记表达式类型,再定义结构体,首成员为类型标记,后续union存储不同类型的对应数据,求值函数通过switch判断标记,读取union对应字段递归计算即可
- Java旧版本:用访问者模式实现相同逻辑,替代模式匹配
- Kotlin:直接用sealed class加when模式匹配,和这段代码写法几乎完全一致
- SML/Pascal:原生支持代数数据类型和模式匹配,直接对应翻译即可
内容的提问来源于stack exchange,提问作者memeeol
相关产品推荐
相关产品推荐

