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 天前
聚乙二醇二生物素,Biotin-PEG-Biotin在生物检测中的应用
scala·bash·laravel·perl
谁黑皮谁肘击谁在连累直升机4 天前
文件读写-成绩分析
scala
小冻梨5 天前
模式匹配-基础使用
scala
顧棟8 天前
JAVA、SCALA 与尾递归
java·开发语言·scala
深兰科技8 天前
坦桑尼亚与新加坡代表团到访深兰科技,促进AI在多领域的应用落地
java·人工智能·typescript·scala·perl·ai大模型·深兰科技
a程序小傲9 天前
scala中的Array
开发语言·后端·scala
kk哥88999 天前
scala 介绍
开发语言·后端·scala
173110 天前
scala中的Array
scala
满山狗尾草11 天前
map的常规操作
scala
渣渣盟12 天前
Flink实时数据写入Redis实战
大数据·scala·apache