首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调用从Kotlin获取非空参数的Java方法?

如何调用从Kotlin获取非空参数的Java方法?
EN

Stack Overflow用户
提问于 2021-12-14 02:10:59
回答 1查看 304关注 0票数 0

初级问题

是否可以从Kotlin调用具有这样一个签名(来自第三方库,因此方法签名不能更改)的Java方法?如果是这样的话,是怎么做的?

代码语言:javascript
复制
class Uncallable {
    void myMethod(@NonNull Void a) {
        System.out.println("Ran myMethod");
    }
}

我可以从另一个Java类调用

代码语言:javascript
复制
Uncallable u = new Uncallable();
u.myMethod(null); // IDE warns about nullability but still runs fine

但从科特林看来,这些选择都行不通

代码语言:javascript
复制
val u = Uncallable()
u.myMethod() // No value passed for parameter 'a'
u.myMethod(null) // Null can not be a value of a non-null type Void
u.myMethod(Unit as Void) // ClassCastException: class kotlin.Unit cannot be cast to class java.lang.Void
u.myMethod(Void)
u.myMethod(Unit)
u.myMethod(Nothing)

类似的问题(比如this one)建议创建一个Java接口层,让我绕过可空性规则。这在这里有效,但我想知道是否有任何方法来调用这没有这样一个额外的层。实际上,我不需要传递一个空值,只需调用该方法。

This question解决了一个类似的问题,但是在那里他们控制了接口,并且可以使用Void?作为类型。

我为什么要这么做?

我不是真的..。但是,我有一些单元测试,它们拦截添加到某些Firebase方法中的addOnSuccessListener回调,并在提供的侦听器上调用onSuccess。该回调的签名使用Void作为其参数类型,以前我可以调用listener.onSuccess(null)

代码语言:javascript
复制
doAnswer { invocation ->
    val args = invocation.arguments
    @Suppress("UNCHECKED_CAST")
    val l = args[0] as OnSuccessListener<Void>
    l.onSuccess(null)
    mMockTask
}.`when`(mMockTask).addOnSuccessListener(ArgumentMatchers.any())

在最近更新了Firebase库之后,似乎在onSuccess的参数中添加了一个onSuccess注释,或者Kotlin进行了更改以开始强制执行

代码语言:javascript
复制
public interface OnSuccessListener<TResult> {
    void onSuccess(@NonNull TResult var1);
}

因此,我不能再调用listener.onSuccess(null) -我得到一个关于非空参数传递null的构建错误。

我可以制作一个VoidCaller Java接口来解决这个问题,

代码语言:javascript
复制
public class VoidCaller {
    static void callSuccessCallback(OnSuccessListener<Void> callback) {
        callback.onSuccess(null);
    }

    static void callFailureCallback(OnFailureListener callback) {
        callback.onFailure(null);
    }
}

,但只有当我将回调更改为

代码语言:javascript
复制
fileRef.delete().addOnSuccessListener { onSuccess() }

代码语言:javascript
复制
fileRef.delete().addOnSuccessListener { _ : Void? -> onSuccess() }

或者,试图将非空类型的it设置为null时出错。

代码语言:javascript
复制
Parameter specified as non-null is null: method com.app.firebaseHelper.deleteImage$lambda-11$lambda-10, parameter it

理想情况下,我希望找到一种直接从Kotlin调用这样一个方法的方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-14 03:35:08

如果您只想传递空对象,但它的构造函数是私有的,则可以使用反射。

代码语言:javascript
复制
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance();

然后你就可以通过了。

既然问题是如何从科特林做这件事,下面是科特林版本。

代码语言:javascript
复制
fun makeVoid(): Void {
    val c: Constructor<Void> = Void::class.java.getDeclaredConstructor()
    c.isAccessible = true
    return c.newInstance()
}

代码语言:javascript
复制
val u = Uncallable()
u.myMethod(makeVoid())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70343009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档