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
相关推荐
昕昕恋恋11 小时前
定向和访问成员变量
scala
IvanCodes2 天前
七、Scala 包、样例类与样例对象
大数据·开发语言·scala
浩浩kids2 天前
Scala • basis
java·开发语言·scala
Java水解11 天前
Scala深入面向对象:类、对象与伴生关系
后端·scala
哈哈很哈哈14 天前
Spark 核心 RDD详解
大数据·分布式·spark·scala
DTS小夏15 天前
Linux 系统 + IDEA+Scala 插件:新手进阶开发指南
linux·scala·intellij-idea
渣渣盟16 天前
Spark核心:单跳转换率计算全解析
大数据·spark·scala·apache
闯闯桑17 天前
Spark 中spark.implicits._ 中的 toDF和DataFrame 类本身的 toDF 方法
大数据·ajax·spark·scala
MOMO陌染20 天前
IDEA环境搭建与输出
scala
闯闯桑22 天前
toDF(columns: _*) 语法
开发语言·前端·spark·scala·apache