如何在 kotlin 中使用 :: 调用带参数的静态方法

How call static method with params using :: in kotlin

想象一下我们需要在 kotlin 中使用 :: 调用带有参数的静态方法的情况。实际上我只能用没有参数的函数来做,例如

Base64::hashCode

但是当我尝试使用

Base64::encodeToString

然后我收到警告

Overload resolution ambiguity. All these functions match. public open fun encodeToString(input: ByteArray!, flags: Int): String! defined in android.util.Base64 public open fun encodeToString(input: ByteArray!, offset: Int, len: Int, flags: Int): String! defined in android.util.Base64

编译器也不接受这种形式

(Base64::encodeToString)( byteArrayOf(2), Base64.DEFAULT)

我想使用 mockito 的新功能来模拟这个方法 here

感谢您提供任何信息!

:: 语法非常有限,因为它不允许泛型类型参数和具有多个参数的方法。但是,没有什么能阻止您像这样传递 lambda 引用:

{ param ->
    param.encodeToString()
}

一般来说,可调用引用语法不能与重载方法一起使用,因为编译器不知道您希望他选择什么变体(在这种情况下使用 2 or 4 参数)。 但这不是这里唯一的问题。

通过这种方式获得的实例类型为KFunction, which in parameterful case treated differently than function types (this is a well known, but still unfixed compiler bug).

因此,我认为您需要使用以下语法模拟 encodeToString 方法的两个重载变体(如果您想使用其中任何一个):

Mockito.mockStatic(Base64::class.java).use { theMock ->
    theMock.`when`<Any> { Base64.encodeToString(any(), any()) }.thenReturn("MyMockString")
    theMock.`when`<Any> { Base64.encodeToString(any(), any(), any(), any()) }.thenReturn("MyMockString")
    assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111))
    assertEquals("MyMockString", Base64.encodeToString(byteArrayOf(), 111, 111, 111))
}

另请注意 Mockito javadocs 说:

We recommend against mocking static methods of classes in the standard library

您可以显式指定类型,因此它知道您要引用哪个函数:

import kotlin.reflect.KFunction2

val encode: KFunction2<ByteArray, Int, ByteArray> = Base64::encode

其中KFunction2表示它是一个2参数函数,ByteArrayInt是参数——最后一个ByteArray是return类型.

::encode是静态函数,所以只是处理调用时传入的参数。相比之下,hashcode() 是一个实例方法,所以即使 调用本身 不接受参数,该函数也会接受一个 Base64 实例(你的东西'正在调用 hashCode():

val hashCode: KFunction1<Base64, Int> = Base64::hashCode

(实例类型,return类型)

这基本上就是它的工作原理 - 您可以定义 encode 函数引用 val 并像往常一样调用它,参数提示将告诉您它知道它是哪个函数。

虽然不能保证它会适用于您正在做的任何事情!