【问题标题】:Call java varargs method from kotlin从 kotlin 调用 java varargs 方法
【发布时间】:2016-04-14 14:26:53
【问题描述】:

我有一个java函数:

public static void initialize(@NonNull Activity activity, Settings... settings) {}

我想从 kotlin 调用它:

fun initialize(activity: Activity, vararg settings: settings) = JavaClass.initialize(activity, settings)

但是编译不出来,告诉我有类型不匹配,Settings是必填项,但是参数是kotlin.Array<out Settings>

我看到它正在尝试将其与签名匹配

public static void initialize(@NonNull Activity activity, Settings settings) {}

但我想使用

public static void initialize(@NonNull Activity activity, Settings[] settings) {}

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    您应该使用以下语法:

    fun initialize(activity: Activity, vararg settings: settings) =
        JavaClass.initialize(activity, *settings)
    

    https://kotlinlang.org/docs/reference/java-interop.html#java-varargs

    【讨论】:

    【解决方案2】:

    Michael's answer 是正确的,不过我想多做一些 cmets。

    之所以不能将 Kotlin vararg 参数传递给需要另一个 vararg 的 Java(或 Kotlin)函数,是因为编译器将 vararg 解析为 Array

    因此,就好像您已将函数声明如下(从函数内部范围的角度来看):

    fun initialize(activity: Activity, settings: Array<Settings>) = //...
    

    这就是为什么我们需要使用扩展* 运算符是不直观的。据我所知,这种设计选择有两个好处:

    1. 扩展运算符除了用于填充变量参数外,还可用于在单个参数和扩展数组之间进行混合匹配。这意味着 Kotlin 为我们提供了一种向 vararg 列表添加额外参数的便捷方式。

      在 Java 中,以下代码无法编译:

      Settings[] settings = //...
      Setting myAdditionalSetting = new Setting();
      JavaClass.initialize(activity, settings, myAdditionalSetting); //Compiler Error 
      

      但是,在 Kotlin 中我们可以这样做:

      JavaClass.initialize(activity, *settings, myAdditionalSetting)
      
    2. 第二个好处是提高了安全性。扩展运算符编译为对 Arrays.copyOf() 的调用,这保证了扩展值的不变性。i 这确保了被调用的函数不会破坏原始数组。

    i:虽然实际的类 references 是不可变的,但它们引用的对象可能仍然是可变的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      相关资源
      最近更新 更多