Kotlin官方参考整理——06.Java互操作

这一部分内容了解大概就行,官方参考讲的很不清楚,实际使用中如果遇到问题再去查详细的资料

概述

Kotlin在设计时就考虑了与Java的互操作性。可以从Kotlin中自然地调用现存的Java代码,在 Java代码中也可以顺利地调用Kotlin代码。

1 在Kotlin中调用Java

Getter和Setter

遵循Java约定的getter和setter方法(名称以get开头的无参数方法和以set开头的单参数方法)在Kotlin中表示为属性。例如:

import java.util.Calendar

fun calendarDemo() {
    val calendar = Calendar.getInstance()
    if (calendar.firstDayOfWeek == Calendar.SUNDAY) {   //会调⽤ getFirstDayOfWeek()
        calendar.firstDayOfWeek = Calendar.MONDAY       //会调⽤ setFirstDayOfWeek()
    }
}

请注意,如果Java类中的某字段只有一个setter,它在Kotlin中并不会作为属性可见,因为Kotlin中不存在只有setter的属性。

返回void的方法

如果一个Java方法返回void,那么从Kotlin中调用时返回Unit。

Java中标识符与Kotlin关键字重名的情况

一些Kotlin关键字在Java中是合法的标识符,如in、object、is等等。比如你在Java代码中定义了一个名为is的函数,那么在Kotlin代码中你是无法直接调用该函数的,因为is会被当成kotlin中的关键字,解决办法:使用反引号将is括起来以表示该函数。

foo.`is`(bar)

空安全和平台类型

来自Java代码的对象在Kotlin中会被特别认为是平台类型(以String为例,其平台类型被表示为String!)。平台类型对应于kotlin中的可空类型还是非空类型是不确定的,换句话说,这个需要由你根据实际来决定,一般情况下,我们会将一个平台类型的对象赋值给一个可空类型的变量,但是如果你能确定此平台类型对象不可能为null的话,也可以将其赋值给一个非空类型的变量。

举个例子:

//java文件:JavaClass.java
package cn.szx.kotlindemo

public class JavaClass {
    public static String getName() {
        if (new Random().nextInt(100) % 2 == 0) {
            return "ZhangSan";
        } else {
            return null;
        }
    }
}
//kotlin文件:Test.kt
package cn.szx.kotlindemo

fun test() {
    /**
     * 调用一个返回字符串的java方法,返回值被认为是平台类型“String!”
     */

    val name1: String? = JavaClass.getName()//将其赋值给一个可空类型的变量
    name1?.substring(1)

    val name2: String = JavaClass.getName()//如果你确信getName()的返回值不可能为null的话,也可以将其赋值给一个非空类型的变量
    name2.substring(1)//如果name2为null的话,会抛出空指针异常
}

Kotlin中的Java泛型

和Java一样,Kotlin在运行时不保留泛型,即对象不携带传递到他们构造器中的那些类型参数的实际类型。即ArrayList<Integer>()ArrayList<Character>()是不能区分的。这使得执行is检测不可能照顾到泛型。Kotlin只允许is-检测星投影的泛型:

if(a is List<Int>)  //错误:无法检查它是否真的是⼀个Int列表
if(a is List<*>)    //OK:不保证列表的内容

此外,Kotlin中的数组是不型变的,这意味着Kotlin中不允许我们把一个Array<String>赋值给一个Array<Any>。而在Java中,数组是协变的,即可以把一个String[]赋给一个Object[]。

受检异常

在Kotlin中,所有异常都是非受检的,这意味着编译器不会强迫你捕获或抛出异常。因此,当你调用一个可能抛出异常的Java方法时,Kotlin不会强迫你做任何事情:

fun render(list: List<*>, to: Appendable) {
    for (item in list) {
        to.append(item.toString()) //Java会要求我们捕获或声明抛出IOException
    }
}

访问Java类的静态成员

Kotlin中没有static的概念。对于Java类中的静态成员,系统会为其生成所在类的伴生对象,我们无法将这样的“伴生对象”作为值来传递,但可以访问其成员,例如:

if (Character.isLetter(a)) {
    ...
}

反射

Java反射适用于Kotlin类,反之亦然。

你可以使用instance::class.java,ClassName::class.java或者instance.javaClass来获得java.lang.Class的实例,然后就可以使用Java的反射机制了。

在Kotlin中使用JNI

Kotlin中使用external关键字来声明本地方法,其他和Java中一样:

external fun foo(x: Int): Double

SAM转换

就像Java8一样,Kotlin支持SAM转换,这意味着lambda表达式可以被自动转换成只有一个方法的Java接口的实现:

view.setOnClickListener {
    Log.e("Log", "view被点击了!")
}

注意,SAM转换只适用于接口,而不适用于抽象类,即使这些抽象类也只有一个抽象方法。

2 在Java中调用Kotlin

属性

Kotlin属性会编译成以下Java元素:

  • 一个getter方法
  • 一个 setter方法
  • 一个私有字段,与属性名称相同(仅限具有幕后字段的属性)

例如,var firstName: String会被编译成以下Java代码:

private String firstName;
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}

包级变量和函数

即顶层变量和函数。会被编译成Java类的静态成员。如:在org.foo.bar包内的example.kt文件中声明的所有的变量和函数,都编译成名为org.foo.bar.ExampleKt的Java类的静态成员。

最后

对Kotlin官方参考的整理到这里就结束了,这只是对Kotlin的一个简单入门。要进一步深入学习Kotlin,建议看《kotlin for android developers》和《Kotlin in Action》这两本书,都是Kotlin官方所大力推荐的。

发布了46 篇原创文章 · 获赞 38 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/al4fun/article/details/73928691