位置:首页 > Scala > Scala缺省参数值在class文件中的实现原理解析

Scala缺省参数值在class文件中的实现原理解析

时间:2026-08-21  |  作者:怪兽小助手  |  阅读:0

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

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

结论

如果函数 f(...) 中用到了缺省参数值,编译后会发生两件事:

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

代码

我们用以下的 Scala 代码来进行探索(请将代码保存为 A.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 文件。

使用 ja vap -p A 命令,能够查看 A.class 中的简要内容。以下是其结果:

Compiled from "A.scala"
public class A {
  public A();
  public void showGreeting(ja va.lang.String, ja va.lang.String, int, int, int);
  public ja va.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() 函数

进一步查看反编译结果

通过 ja vap -v -p A 命令,能够查看 A.class 的详细内容。

倘若手动将结果转换为 ja va 代码,难免会觉得枯燥乏味。此时不妨借助 Visual Studio Code 里的 Decompiled Ja va Class File 来帮忙

转化结果如下

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

public class A {
    public A() {
        super();
    }
   
    // 为了便于阅读,这个函数的缩进做了些调整
    public void showGreeting(
        final ja va.lang.String greeting, 
        final ja va.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 ja va.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
        );
   }
}

调用过程说明

Scala 代码中的 showGreeting(name = "小明", month = 7, day = 29)class 文件中会拆分成 3 个步骤

其他

最后一张图是如何画出来的

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

---
config:
  layout: dagre
---
flowchart TD
 subgraph s1["In _Scala_ source code"]
        A["_**callerFunction()**_ calls _**showGreeting(name = "小明", month = 7, day = 29)**_ (_greeting/year_ parameters ha ve default values)"]
  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

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多