Kotlin语言【java和kotlin之间互相操作】
- kotlin调用java
- java调用kotlin
- @JvmName
- @JvmField
- @JvmOverloads
- @JvmStatic
- @Throws
- 函数类型
定义一个java类
public class Jhava {
private int hitPoints = 23423144;
public String utterGreeting() {
return "HELLO";
}
public String determinFriendshipLevel() {
return null;
}
public int getHitPoints() {
System.out.println("--------hitPoints--------");
return hitPoints;
}
public void setHitPoints(int hitPoints) {
this.hitPoints = hitPoints;
}
}
kotlin调用java
//创建一个java对象
val adversary = Jhava()
println(adversary.utterGreeting())
val level: String? = adversary.determinFriendshipLevel()
//这里不确定,要使用空安全操作符
level?.toLowerCase();
//这里会映射回对应的java类型int
println(adversary.hitPoints.javaClass)
//java那边是私有的,必须要提供get方法,kotlin会调用get方法获取
//java那边是公开的,就不需要了
println(adversary.hitPoints)
//这里不需要调用set方法直接赋值,条件是java那边要提供set方法
adversary.hitPoints = 222;
java调用kotlin
比如下面的Spell的kotlin文件,当中没有定义类;
package com.yclids.android_kotlin_study.test
//在java中被当做静态变量看待
val spells = listOf("A", "B", "C", "D")
//在java中被当做静态方法看待
fun makeProclamation() = "Greeting china"
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
println("Mmm ... you hand over some delicious $leftHand and $rightHand");
}
上面的kotlin文件编译后生成的类型文件名称是SpellKt,在Java中调用如下:
//如果没有使用@file:JvmName("Spell"),就要使用SpellKt才可以【转成java带有Kt】
SpellKt.makeProclamation();
//java中访问kotlin中某个字段,要使用get方法,因为没有添加 @JvmField
SpellKt.getSpells();
//java中访问kotlin中某个方法的重载,要使用,因为没有@JvmOverloads,所以不可以重载
SpellKt.handOverFood("left", "right");
下面就介绍@JvmName、@JvmField、@JvmOverloads等使用
@JvmName
- 可以使用@JvmName注解指定编译类的名字
- Kotlin顶层函数在java里都被看做静态方法看待和调用
比如:Spell.kt
//添加这个声明之后在java那边可以使用Spell了
@file:JvmName("Spell")
package com.yclids.android_kotlin_study.test
//在java中被当做静态变量看待
val spells = listOf("A", "B", "C", "D")
//在java中被当做静态方法看待
fun makeProclamation() = "Greeting china"
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
println("Mmm ... you hand over some delicious $leftHand and $rightHand");
}
在Java中可以如下使用:
public class Zion {
public static void main(String[] args) {
//使用@file:JvmName("Spell")
Spell.makeProclamation();
Spell.getSpells();
Spell.handOverFood("left", "right");
}
}
@JvmField
- kotlin中使用这个注解以后,字段就公开了,java可以直接访问这个字段
@JvmField
val spells = listOf("A", "B", "C", "D")
Zion.java
public class Zion {
public static void main(String[] args) {
SpellKt.makeProclamation();
//对字段使用了@JvmField,后直接访问
List<String> spells = SpellKt.spells;
SpellKt.handOverFood("left", "right");
}
}
@JvmOverloads
- @JvmOverloads注解协助产生kotlin函数的重载,便于在Java中使用
kotlin中
@JvmOverloads
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
println("Mmm ... you hand over some delicious $leftHand and $rightHand");
}
java中使用
SpellKt.makeProclamation();
SpellKt.getSpells();
//对方法使用@JvmOverloads
SpellKt.handOverFood();
SpellKt.handOverFood("left");
SpellKt.handOverFood("left", "right");
@JvmStatic
- @JvmField注解还能用来以静态方式提供伴生对象里定义的值
- @JvmStatic注解的作用类似于@JvmField,允许你直接调用伴生对象里的函数
比如下面的kotlin中的类:
package com.yclids.android_kotlin_study.test
class Prod {
@JvmField
//在java中被当做普通变量看待
val spells = listOf("A", "B", "C", "D")
@JvmOverloads
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
println("Mmm ... you hand over some delicious $leftHand and $rightHand");
}
companion object {
@JvmField
val MAX_SPELL_COUNT = 10
@JvmStatic
fun getSpellbookGreeting() = println("I am the Great Grimoire!")
}
}
在java调用
//对字段使用了@JvmField
List<String> spells = new Prod().spells;
//对方法使用了@JvmOverloads
new Prod().handOverFood();
new Prod().handOverFood("left");
new Prod().handOverFood("left", "right");
//对伴生对象里的字段使用了@JvmField
int maxSpellCount = Prod.MAX_SPELL_COUNT;
//对伴生对象里的方法使用了@JvmStatic
Prod.getSpellbookGreeting();
@Throws
- 抛出一个需要检查的指定异常,java和kotlin有关异常检查的差异让@Throws注解给解决掉了
@Throws(IOException::class)
fun acceptApology() {
throw IOException()
}
在Kotlin的方法中添加上面的注解以后,就可以在Java当中捕获异常了
try {
//kotlin那边使用了@Throws注解,这里可以捕获异常
SpellBookKt.acceptApology();
} catch (IOException e) {
e.printStackTrace();
}
函数类型
- 在java中,Kotlin函数类型使用FunctionN这样的名字的接口来表示的
- FunctionN中的N代表值参数目。每一个FuncationN都包含一个invoke函数,专用于调用函数类型函数
在Spell中
//定义一个函数类型
val m: (String) -> Unit = {
println(it);
}
比如上面的函数类型,在Java中就要使用Function来表示,有一个参数,那就是Function1,方法调用就用invoke
Function1<String, Unit> m = SpellBookKt.getM();
m.invoke("两只老虎");