浅谈Kotlin与Java互操作(下)

263 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情

前言

Kotlin is 100% interoperable with Java and Android

Kotlin官网的一句标语,其旨意是表达kotlin的Interoperable-互操作特性

互操作就表示Kotlin中可以调用 Java的开放接口来访问成员属性和成员方法,同时在Java代码中也百分百兼容Kotlin代码,本篇就来探讨一下 Java 调用 Kotlin。

文章概览

Java 调用 Kotlin.png

调用Kotlin中“Static” fields,“Static” methods

Java中,用关键字static 来修饰静态方法和字段,直接通过"类名.属性名"进行访问。而 Kotlin 中没有static关键字,但可以用伴生对象(companion object)方式设置字段或者方法。

Java中调用时,可通过 类型.成员类名.伴生对象.成员 的方式访问,用以下示例:

创建Department类并声明一个名为 Fruit 伴生对象,该对象中有静态字段name,用注解 @JvmStatic修饰方法 sayHello()

class Department {
    companion object Fruit {
        var name = "Apple" // 静态字段
        @JvmStatic
        fun sayHello() {  // 静态方法
             println(name)
        }
    }
}

上述代码,伴生对象中包含一个静态字段name,用注解@JvmStatic声明一个静态方法sayHello()

在Java 中调用Kotlin 伴生对象的字段和方法:

public class Demo {
    public static void main(String[] args) {
        Department.Fruit.setName("Any"); // 类名.伴生对象.成员 的方式访问     
        Department.Fruit.sayHello();     
        Department.sayHello();           // 类名.成员方法 的访问方式
    }
}

运行结果:

Any
Any

上面示例,Java 可通过 类名.伴生对象名.getXX()/setXX() 来访问 Kotlin 静态字段,通过 类名.伴生对象.方法名类名.方法名 来访问 Kotlin 中静态方法。

调用Kotlin中 Instance fields

Java中,访问某个字段,一般通过getXX()/setXX()方法来获取,在Kotlin中,是通过对象.字段名来获取。

在 Java 中将 Kotlin 属性公开,要使用@JvmField对其进行修饰, 官方文档上对该字段的约束:

  • 不是私有的
  • 没有 或 修饰符是open override const
  • 不是委托属性
class User(id: String) { 
    @JvmField val ID = id 
}

上述代码中,给ID字段添加了@JvmField注解,可以使ID字段在Java中直接以对象.ID的方式访问

// Java 
class JavaClient { 
    public String getID(User user) { 
        return user.ID; 
    } 
}

调用Kotlin中 Package-level functions

Kotlin中的包级函数:在包中直接声明的函数,它在编译时最终会生成一个静态的函数,Java中调用该函数有方式:

  • 包级函数所在文件会生成名为“文件名Kt”的类,以 文件名Kt.函数名() 的形式调用包级函数
  • 若要编译包级函数的类名(改成与Java类名类似),则需在Kotlin文件添加@file:JvmName("类名")的注解

示例1

// app.kt 
package org.example 
class Util 
fun getTime() { /*...*/ }

在Java中调用上述声明的方法和类,文件名Kt.函数名() 的形式调用

// Java 
new org.example.Util(); 
org.example.AppKt.getTime();

示例2 若要生成设置自定义名称的Java类,请使用注释:@JvmName

@file:JvmName("DemoUtils") 
package org.example 
class Util 
fun getTime() { /*...*/ }

在Java中则通过自定义的类名调用

// Java 
new org.example.Util(); 
org.example.DemoUtils.getTime();

注意
在Java中不可通过 new 关键字来创建Kotlin中编译后的PackageFunctionKt类的对象

关键字冲突

一些Java中的常规标识符,确是Kotlin 关键字,如in、Object、is等。Java中使用Kotlin中的关键字作为方法名,则需要用反引号字符转义来调用。\

Keyword Java class中声明一个is()方法

public class Keyword {
    public boolean is(Object o) { // 声明 is方法
        return true;
    }
}

在Kotlin中,调用上述Java代码中创建的is()方法

fun main() {
    var key = Keyword()     // 声明对象
    var result = key.`is`("key")  // 通过反引号转义再调用is()
    println(result)
}

运行结果:

true

在上述代码中,由于在Kotlin中is是关键字,若想要调用is()方法,则需通过反引号转义来实现调用。

调用Kotlin中集合类

Kotlin中的List和MutableList映射到Java中的List类型,Map和Set也类似,需注意的点:通过listof()方法创建的集合是不能扩展或删除元素。

Klist.kt中声明 getList()方法,返回值是一个集合,通过listof()方法创建。

fun getList():List<String>{
   return listOf("沐小琪","小汤圆","沐沐")
}

在Java中通过调用上述Kotlin的 getList()来获取List集合并修改元素

public class Demo {
    public static void main(String[] args) {
        List<String> list = ListKt.getList();  // 映射到List
        list.set(2, "子不语Any");                   // 修改集合中下标为2的元素
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
   }
}

运行结果:

沐小琪
小汤圆
子不语Any

在上述代码中,通过set()方法修改list集合中下标为2的元素。

需注意:Java中可以通过add()方法向集合中添加或修改元素,但此处不可这样写,不然在运行时报错

以上是总结平常开发中Java调用Kotlin代码的情形,需要了解更详细可以参看Kotlin官方文档。

掘金(JUEJIN)  一起分享知识, Keep Learning!