title | date | author | tags | keywords | categories | reward | reward_title | reward_wechat | reward_alipay | source_url | translator | translator_url |
---|---|---|---|---|---|---|---|---|---|---|---|---|
[译]Making Platform Interop even smoother |
2014-10-06 06:20:00 -0700 |
Hadi Hariri |
官方动态 |
false |
Have a nice Kotlin! |
与 JVM 100%可互操作,随后使用 JavaScript,一直是 Kotlin 的首要任务。随着现有代码的数量和丰富的 JVM 生态系统,具有互操作性和有效性的功能至关重要。 随着即将发布的 M9,我们已经改进了这一点,使集成更加无缝。
处理空值是涉及 Java 互操作性的最大问题之一。几乎任何 Java 方法可能会返回 null,所以 Kotlin 将 Java 类型视为可以为空的,我们还是要求使用安全调用(?。)运算符或 notnull-assertion(!!)来避免编译错误:
{% raw %}
{% endraw %}val x = javaCanReturnNull() // Java call that can return null
{% raw %}
{% endraw %}尝试将值x传递给以下函数:
{% raw %}
{% endraw %}fun nullNotAllowed(value: String) {}
fun nullAllowed(value: String?) {}
{% raw %}
{% endraw %}在第一种情况下,Kotlin 编译器会发出错误。这意味着对nullNotAllowed的调用将需要:
{% raw %}
{% endraw %}val x = javaCanReturnNull()
nullNotAllowed(x!!)
{% raw %}
{% endraw %}从 M9 开始,情况就不一样了。这允许更清洁的代码,并避免过度使用?和!!操作员在与 Java 进行交互时。 同样的方式,在实现 Java 接口时,可能具有潜在的空参数的方法不再需要在 Kotlin 中将这些声明声明为可空。例如,给出:
{% raw %}
{% endraw %}public interface SomeFoo {
void foo(String input, String data);
}
{% raw %}
{% endraw %}当在 Kotlin 实施这个时:
{% raw %}
{% endraw %}public class SomeInterestingFoo(): SomeFoo {
override fun foo(input: String, data: String?) { // String? no longer required
...
}
}
{% raw %}
{% endraw %}参数输入不再需要类型为String?。您可以选择使用String还是String? - 取决于其实际含义。在这个例子中,我们选择输入不为空,并且数据为空。
Kotlin 有对象声明,可以看作单身人士。这些都是从 Java 中消耗的,尽管不是最好的语法。给定:
{% raw %}
{% endraw %}object Foo {
fun bar() {
}
}
{% raw %}
{% endraw %}从 Kotlin 消费,将是:
{% raw %}
{% endraw %}Foo.bar()
{% raw %}
{% endraw %}而从 Java 它将看起来像这样:
{% raw %}
{% endraw %}Foo.INSTANCE$.bar()
{% raw %}
{% endraw %}随着下一个版本,我们可以通过简单地向函数声明添加一个注释,从与 Kotlin 相同的方式从 Java 调用该方法:
{% raw %}
{% endraw %}object Foo {
platformStatic bar() {
}
}
{% raw %}
{% endraw %}使代码更清洁。同样适用于类对象。
platformStatic的另一个好处是在使用某些 Java 库(例如 JUnit)时删除了一些存在的 showstoppers。特别地,后者在使用时需要 Java 中的静态方法 理论 。对此的解决方法相当乏味。幸运的是,情况已经不再如此。我们可以使用platformStatic注释来解决这个问题 问题 。
{% raw %}
{% endraw %}RunWith(javaClass<Theories>())
public class TestDoubling {
class object {
platformStatic DataPoints
public fun values(): IntArray {
return intArray(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
}
}
Theory
public fun testDoubling(a: Int?) {
Assert.assertThat<Int>(doubling(a!!), `is`<Int>(a * 2))
}
public fun doubling(value: Int): Int {
return value * 2
}
}
{% raw %}
{% endraw %}当有重载的方法使用泛型,如:
{% raw %}
{% endraw %}fun Iterable<Long>.average(): Double {
...
}
fun Iterable<Int>.average(): Double {
...
}
{% raw %}
{% endraw %}当从 Kotlin 调用这些可能时,尝试从 Java 调用它们是由于类型擦除而有问题的。类似于platformStatic,我们引入了允许重命名该函数的platformName注释,以便在从 Java 调用时,使用新的给定名称:
{% raw %}
{% endraw %}fun Iterable<Long>.average(): Long {
...
}
platformName("averageOfInt") fun Iterable<Int>.average(): Int {
...
}
{% raw %}
{% endraw %}现在可以从 Java 调用如下:
{% raw %}
{% endraw %}averageOfInt(numbers)
{% raw %}
{% endraw %}请注意,这是 不是唯一的用例 for platformName。
Kotlin 的私人私人财产不再生成属性访问器,这意味着 冲突 使用现有的getXYZ方法 不必要地发生。在 Java 中执行以下界面:
{% raw %}
{% endraw %}public interface SomeFoo {
String getBar();
}
{% raw %}
{% endraw %}如果我们要在 Kotlin 中实现这个接口,而我们的类有一个名为bar的私有属性,在 M8 和以前的版本中它会引起冲突,我们必须将属性命名为与< em> bar*。从 M9 开始,情况就不一样了。因此,以下代码完全有效:
{% raw %}
{% endraw %}public class SomeInterestingFoo(private val bar: String): SomeFoo {
override fun getBar(): String {
...
}
}
{% raw %}
{% endraw %}随着 M9 中的这些变化,我们已经删除了一些障碍,更重要的是使 Java 和 Kotlin 之间的互操作性更加清晰。虽然这些改进可以使消费现有的 Java 代码更加愉快,但它也允许在 Kotlin 中编写新的库和功能以及从 Java 中消耗这些库的更好的体验。 和往常一样,我们会喜欢反馈。让我们知道你的想法。 注意:M9 尚未发布,但您可以在夜间版本中找到这些功能*