Scala 的缺省参数值 (default parameter value) 在 class 文件中是如何实现的?

Scala 的缺省参数值 (default parameter value) 在 class 文件中是如何实现的?

Scala 支持 缺省参数值,那么这一特性在 class 文件中是如何做到的呢?本文对此进行介绍。

结论

如果函数 f(...) 中用到了缺省参数值,那么

  • class 文件中会为每一个缺省值生成可以提供这个值的函数,函数名看起来是 f$default$N() 这种格式 (N 表示这个参数的位置,从 1 开始计算)
  • class 文件中,调用方会先调用 f$default$N() 这样的函数把缺省值填好,然后再对 f(...) 进行普通的函数调用

代码

我们用以下的 Scala 代码来进行探索(请将代码保存为 A.Scala

Scala 复制代码
class A {
  def showGreeting(
    greeting: String = "Hello",
    name: String,
    year: Int = 2025,
    month: Int,
    day: Int
  ): Unit = {
    println(s"${greeting} ${name}, today is ${year}-${month}-${day}")
  }

  def callerFunction(): Unit = {
    showGreeting(name = "小明", month = 7, day = 29);
  }
}

scalac A.scala 命令进行编译之后,会生成 A.class 文件。用 javap -p A 命令可以查看 A.class 中的简要内容。 结果如下

text 复制代码
Compiled from "A.scala"
public class A {
  public A();
  public void showGreeting(java.lang.String, java.lang.String, int, int, int);
  public java.lang.String showGreeting$default$1();
  public int showGreeting$default$3();
  public void callerFunction();
}

class 文件里,A 类有 5 个函数

  1. 构造函数 A()
  2. showGreeting(String, String, int, int, int) 函数
  3. showGreeting$default$1() 函数
  4. showGreeting$default$3() 函数
  5. callerFunction() 函数

javap -v -p A 命令可以查看 A.class 中的详细内容。 如果自己手动把结果转化为 java 代码,会有些枯燥,可以借助 Visual Studio Code 里的 Decompiled Java Class File 的帮助 ⬇️

可以手动将结果转化为 java 代码,结果如下 ⬇️

java 复制代码
// 以下 java 代码是我在 Visual Studio Code 的帮助下手动转化的,不保证绝对准确,仅供参考

public class A {
    public A() {
        super();
    }
   
    // 为了便于阅读,这个函数的缩进做了些调整
    public void showGreeting(
        final java.lang.String greeting, 
        final java.lang.String name, 
        final int year, 
        final int month, 
        final int day) {
        scala.Predef$.MODULE$.println(
            new StringBuilder(14).
                append(greeting).
                append(" ").
                append(name).
                append(", today is ").
                append(year).append("-").
                append(month).
                append("-").
                append(day).
                toString()
            );
    }

    // 用于为 showGreeting(...) 函数里的第 1 个参数(即 greeting)提供缺省值
    public java.lang.String showGreeting$default$1() {
        return "Hello";
    }

    // 用于为 showGreeting(...) 函数里的第 3 个参数(即 year)提供缺省值
    public int showGreeting$default$3() {
        return 2025;
    }

    // 为了便于阅读,这个函数的缩进做了些调整
    public void callerFunction() {
        this.showGreeting(
            this.showGreeting$default$1(), // 获取 greeting 参数的缺省值
            "小明",
            this.showGreeting$default$3(), // 获取 year 参数的缺省值
            7,
            29
        );
   }
}

调用 callerFunction() 时,主要步骤如下 ⬇️

其他

主要步骤是如何画出来的

我是在 mermaid.live/ 上画出来的,用到的代码如下 ⬇️

text 复制代码
---
config:
  layout: dagre
---
flowchart LR
 subgraph "主要步骤"
 subgraph s1["In _Scala_ source code"]
        A["_**callerFunction()**_ calls _**showGreeting(...)**_ with explicit _**name/month/day**_ parameters"]
  end
 subgraph s2["In _class_ file"]
      X["Step1: _**callerFunction()**_ populates _**greeting**_ parameter with the return value from _**showGreeting$default$1()**_"]
      Y["Step2: _**callerFunction()**_ populates _**year**_ parameter with the return value from _**/showGreeting$default$3()**_"]
      Z["Step3: _**callerFunction()**_ calls _**showGreeting(...)**_ with _5_ explicit parameters"]
  end
    s1 -- 转化为 --> s2
end
相关推荐
数据智能老司机4 天前
函数式事件驱动架构——交易系统(可观测性)
架构·scala·响应式设计
数据智能老司机4 天前
函数式事件驱动架构——带副作用的流
架构·scala·响应式设计
IvanCodes5 天前
二、Spark 开发环境搭建 IDEA + Maven 及 WordCount 案例实战
大数据·spark·scala
渣渣盟15 天前
Flink数据流高效写入MySQL实战
mysql·flink·scala
开开心心就好15 天前
专业PPT图片提取工具,操作简单
javascript·电脑·powerpoint·scala·erlang·perl·myeclipse
开开心心就好18 天前
电脑息屏工具,一键黑屏超方便
开发语言·javascript·电脑·scala·erlang·perl
linweidong1 个月前
一站式用AI编程神奇Cursor/Trae(VScode环境)开发运行Scala应用
大数据·vscode·后端·大模型·scala·ai编程·cursor
白总Server1 个月前
GaussDB 分布式数据库调优(架构到全链路优化)
java·网络·c++·架构·go·scala·数据库架构
小伍_Five1 个月前
spark数据处理练习题番外篇【下】
java·大数据·spark·scala