我正在将代码库从 Java 转换为 Kotlin。现有的代码库使用
CompletableFuture
进行大量异步操作,我正在将许多异步方法迁移到 Kotlin 协程。但在此过程中,我仍然会有需要接收 CompletableFuture<something>
的 Java 方法,因此我最终得到的代码在概念上类似于以下内容。
(注意:我的实际代码不会像这样阻塞,并且实际上做了有用的工作 - 这个问题只是关于 Java 和 Kotlin 之间的 API 签名。)
public class MyClass {
MyKotlinClass kotlinObject = new MyKotlinClass();
public String doSomethingBlocking() {
CompletableFuture<String> future = kotlinObject.getString();
return future.get();
}
}
class MyKotlinClass {
val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
fun getString(): CompletableFuture<String> = scope.future {
doInternalThingWithString()
}
private suspend fun doInternalThingWithString(): String {
// Pretend we called something async that returns a string.
return "Here's the async string you wanted."
}
}
这工作得很好 - 向外的
getString()
方法返回 CompletableFuture<String>
,这在 Java 中是完全有效的。
但是,Java 泛型不能包含原始类型,我的用例是我实际上需要在 Java 端处理
byte[]
- 我的代码将下载二进制文件并将其内容作为字节数组返回供以后使用。所以我可以在 Kotlin 中做到这一点:
fun getByteArray(): CompletableFuture<ByteArray> = scope.future {
doInternalThingWithByteArray()
}
private suspend fun doInternalThingWithByteArray(): ByteArray {
// Pretend we called something async that returns a ByteArray
return byteArrayOf(10, 20, 30)
}
但是Java无法编译这个:
public byte[] doSomethingElseBlocking() {
CompletableFuture<byte[]> future = kotlinObject.getByteArray();
return future.get();
}
...因为它不支持原始类型的泛型,而且据我所知,它也不喜欢数组的泛型。因此,我会遇到一个问题,让我的 Java 代码与返回字节数组、整数数组、布尔数组等的 future 的 Kotlin 方法交互。
在这段代码的纯 Java 版本中,我通过围绕字节数组创建一个包装类来解决这个问题,这样我就可以在泛型中返回该类的实例,而不是原始数组本身。如果可以的话,我想避免这样做。
我要转换的项目是为 JDK 11 编写的。我们正在将其迁移到 JDK 21,我正在将其核心部分提取到一个纯 Kotlin 共享库,也针对 JDK 21。这就是这个问题的原因。
谢谢!让我知道我可以提供哪些其他信息来进一步澄清这一点。由于我自己无法找到这个问题的答案,我认为这可能是一个异常情况。
好吧,我显然有点傻。我上面写的代码实际上是有效的 - 正如 Slaw 在评论中提到的,Java 将
byte[]
视为对象,而不是基元,并且 CompletableFuture<byte[]>
实际上工作得很好。
我一生都不记得为什么我过去遇到了麻烦,但显然我的问题的前提是错误的,所以我发布这个答案是为了其他像我一样困惑的人这里。抱歉给您带来麻烦了!