Kotlin学习之路

Kotlin基本语法之(九)Kotlin与java互操作

2019-05-31  本文已影响0人  wanderingGuy

实际开发我们即使决定切换到Kotlin语言,但由于历史模块或依赖的第三方库仍是使用Java开发的,这也就不可避免在二者之前产生相互调用,虽然官方宣称100%兼容,但实际使用过程中仍有一些小问题需要注意。

Kotlin调用Java

get/set方法

由于Kotlin中并不需要显式的声明get/set方法,所以对于访问Java标准实体类中的属性,可直接通过属性名称。

Animal.java
public class Animal {
    private int age;
    private String name;

    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }
    //...getter/setter
}

kotlin中这样使用

val animal = Animal(3, "twodog")
println(animal.age)//读取
animal.name = "dahuang"//修改

获取Java类型

若想获取某个java类的类型需通过Kotlin的反射实现。::得到Kotlin类型,继续调用扩展属性java得到其对应的java类型。

val animal = Animal(3, "twodog")
println(animal::class.java.simpleName)
//输出
Animal

wait/notify

我们知道kotlin中Any与Java中的Object对应,但问题是Any类中只有equals/hashCode/toString三个方法。

public open class Any {

    public open operator fun equals(other: Any?): Boolean

    public open fun hashCode(): Int

    public open fun toString(): String
}

那并发编程用到的等待唤醒wait/notify方法如何使用呢?事实上官方不建议使用普通对象锁,取而代之的是Lock锁。如果你确实想使用可以通过下面的方法。

(foo as java.lang.Object).wait()

即先强转为java的Object类型,再使用并发函数。

Java调用Kotlin

get/set方法

java访问Kotlin的属性应使用对用的getter/setter方法。

//Client.kt
data class Client(var name: String)

//java test
Client client = new Client("zhangsan");
System.out.println(client.getName());
client.setName("lisi");

另外,Kotlin中默认会给属性添加getter/setter方法(val类型的没有setter),这势必会造成一定的性能损耗,可为属性添加@JvmField注解去掉此默认行为。

//去掉NO属性的getter/setter
data class Client(var name: String,@JvmField  var NO: Int) 

顶级函数

之前章节讲到顶级函数是用静态方法实现的,而该静态方法所在的类为kotlin文件名+Kt。

// TestPackageMethod.kt
fun sayHello(name: String) {
    println("hello $name")
}
//java test
TestPackageMethodKt.sayHello("zhao");

如果想改变生成的默认类名,可以在kt文件中package声明前添加注解。

//改变默认生成的Java类名
@file:JvmName("MyPackageMethodTest")

object静态函数

之前讲到object类为单例类,内部实现是通过饿汉式实现单例,在类中有一个本类的静态实例,因此当在java中访问此object类中方法的时需通过此静态实例,该实例的默认名字统一为INSTANCE

//ObjectTest.kt
object ObjectTest {
    fun objectMethod() {
    }
}

//java call
ObjectTest.INSTANCE.objectMethod();

伴生对象

伴生对象同样是通过静态实现,只不过静态方法在一个Companion内部类中,因此Java调用需显示声明Companion类名。

//TestStatic.kt
open class TestStatic {
    companion object {
        fun create(): TestStatic {
            return TestStatic()
        }
    }
}

//java call
TestStatic.Companion.create()

异常检查

与Java语言非常大的不同是Kotlin不做异常检查,这就导致在Java中声明的检查异常不需在Kotlin代码中捕获,从而发生意想不到的崩溃,反之亦然。

//TestKotlinException.kt
object TestKotlinException {
    //抛出异常但方法不需异常声明
    fun getException() {
        throw Exception("I am an exception in kotlin")
    }
}

//java call
public static void testException() {
    //编译通过 但运行会发生异常
    TestKotlinException.INSTANCE.getException();
}

如果想改变此默认行为,我们需要在Kotlin方法前添加@Throws(Exception::class)注解。

@Throws(Exception::class)
fun getException() {
    throw Exception("I am an exception in kotlin")
}

此时java调用端会出现期望的编译错误。

//unhandled exception: java.lang.Exception
TestKotlinException.INSTANCE.getException();
上一篇下一篇

猜你喜欢

热点阅读