Kotlin
中的运算符重载在 class
文件中是如何实现的?
结论
以 +
这个二元运算符为例,
- 如果
kotlin
代码有operator fun plus(...)
这样的方法定义,那么class
文件中会有对应的plus
方法出现。 - 反之,如果
class
文件中有签名正确的plus
方法(即使这个方法是通过编译java
代码而生成的),那么kotlin
也可以将其视为运算符重载
代码
我们用以下代码来进行探索,请将其保存为 Vector.kt
kotlin
data class Vector(val x: Double, val y: Double) {
operator fun plus(other: Vector): Vector {
return Vector(x + other.x, y + other.y)
}
}
fun main(args: Array<String>) {
val v1 = Vector(1.0, 0.0)
val v2 = Vector(0.0, 1.0)
val sum = v1 + v2
println("The sum is: $sum")
}
用 kotlinc Vector.kt
命令编译之后,会生成 Vector.class
和 VectorKt.class
。 在 Intellij IDEA
中使用 Show Kotlin Bytecode
功能可以看到这两个 class
文件的内容。 通过对比以下两者,会发现 kotlin
代码中的 v1 + v2
和 java
文件里的 v1.plus(v2)
是对应的。
Vector.kt
- 对
VectorKt.class
进行decompile
操作而得到的java
文件

这么说来 Vector.class
中应该有名为 plus
的方法。 对 Vector.class
进行 decompile
操作后,会得到一个 java
文件,在这个 java
文件中可以找到一个名为 plus
的方法。

看起来 kotlin
代码中重载的运算符在 class
文件中会变成普通的方法(例如 kotlin
里重载的 +
操作,在 class
文件中会转化为名为 plus
的方法)。
如果上述猜测成立的话,即使我们用 java
代码定义 plus
方法,kotlin
代码应该也可以把它当作运算符重载来处理。
我们写一点 java
代码来验证一下。下面定义了一个简单的复数类,其中有一个 plus
方法,可以将两个复数相加(请将下方的 java
代码保存为 ComplexNumber.java
)。
java
public class ComplexNumber {
private double r;
private double i;
public ComplexNumber(double r, double i) {
this.r = r;
this.i = i;
}
public double getR() {
return r;
}
public double getI() {
return i;
}
public ComplexNumber plus(ComplexNumber another) {
return new ComplexNumber(this.r + another.r, this.i + another.i);
}
}
然后再通过以下的 kotlin
代码来使用上面的复数类(请将下方的 kotlin
代码保存为 A.kt
)
kotlin
fun main(args: Array<String>) {
val cn1 = ComplexNumber(1.0, 1.0)
val cn2 = ComplexNumber(1.0, 1.0)
val sum = cn1 + cn2
println("r is: ${sum.r}")
println("i is: ${sum.i}")
}
以下命令可以编译 ComplexNumber.java
和 A.kt
,以及运行 A.kt
中的 main
方法。
bash
javac -g -parameters ComplexNumber.java
kotlinc -cp . A.kt
kotlin AKt
运行结果如下 ⬇️
运行结果符合预期。
不过上面的描述毕竟只是猜测,有没有比较可靠的文档呢?
Operator overloading
一文中的 Arithmetic operators
小节 提到

看来 +
/-
/*
//
/%
/..
/..<
这几个 operator
都会被 compiler
转化为对应的方法调用(对应的具体方法请参考上图)。
另外,我在 Calling Java from Kotlin
一文的 Operators
小节 中找到到了如下的内容

可见,如果在 java
中定义好 plus
/minus
/times
/div
等方法,然后从 kotlin
代码中以运算符重载的方式去调用这些方法是可行的。
参考资料
kotlinlang.org/ 网站关于以下内容的介绍