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
相关推荐
abcy07121317 小时前
scala playframework 搭建与新建controller教程
scala
lpfasd1231 天前
编程语言榜单变迁分析
开发语言·后端·scala
戮漠summer23 天前
Missing Semester 计算机教育中缺失的一课 Lecture 01 Shell
开发语言·后端·scala
醉熏的石头1 个月前
Ubuntu 中的编程语言(中)
linux·ubuntu·scala
Irene19911 个月前
Scala、Java、Python、JavaScript 的核心特性和应用场景(Python 的“单机“局限性:GIL 机制导致的多核并行缺陷)
java·javascript·python·scala
李白的天不白2 个月前
确认 Nginx 配置文件是否真的生效
scala
醉颜凉2 个月前
Scala自定义Monad实战:从理论到应用的完整指南
大数据·算法·scala
那晚的她2 个月前
Scala中Set集合
开发语言·后端·scala
IvanCodes2 个月前
二、Scala流程控制:分支与循环
大数据·scala
Veggie262 个月前
【Scala PyTorch深度学习】PyTorch On Scala系列课程 第十四章 29 PyTorch模型扩展自定义Module【AI Infra3】[PyTorch Scala硕士研一课程】
人工智能·深度学习·scala