Kotlin: make Java function callable infix

2020-04-08 01:18发布

问题:

Tried to make pow function from BigInteger class available as infix function with the same name. The problem is that now the pow infix operator calls itself recursively.

Is it possible to make Java function callable using infix operator with same name as function?

package experiments

import java.math.BigInteger

infix fun BigInteger.pow(x: BigInteger): BigInteger {
    return this.pow(x);
}

fun main(args : Array<String>) {
    val a = BigInteger("2");
    val b = BigInteger("3");

    println(a + b)
    println(a pow b)
}

Causes:

Exception in thread "main" java.lang.StackOverflowError
    at kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull(Intrinsics.java:126)
    at experiments.KotlinTestKt.pow(KotlinTest.kt)
    at experiments.KotlinTestKt.pow(KotlinTest.kt:6)

If I were defining my own Java class (rather than using a library class), is there any way to mark the Java method as infix? Perhaps an annotation?

回答1:

This is because when you're doing:

this.pow(x)

You're actually recursing your infix function. BigInteger doesn't have pow function that takes another BigInteger-- that's what you're defining here. And don't forget, infix functions can still be called with the dot operator!

What you probably meant to write was this:

infix fun BigInteger.pow(x: BigInteger): BigInteger {
    // Convert x to an int
    return pow(x.longValueExact().toInt())
}

fun main(args : Array<String>) {
    val a = BigInteger("2")
    val b = BigInteger("3")

    println(a + b)
    println(a pow b)
}

If you want to reuse BigInteger's pow method, we need to convert to an int. Unfortunately, this is potentially lossy and may overflow. You might want to consider writing your own pow method if this is a concern.

There is no way to mark a Java method "natively" as infix. You can only accomplish this by using a wrapper.



标签: kotlin