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
个函数
- 构造函数
A()
showGreeting(String, String, int, int, int)
函数showGreeting$default$1()
函数showGreeting$default$3()
函数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