前言
在上一篇中,主要讲解了Kotlin对应的函数式编程。在这一篇中,将会讲解Kotlin与Java之间的相互调用!
话不多说,直接开始!
1、Kotlin调用Java
1.1 属性读写操作
进入TestJava
public class TestJava {
public int getHitPoints() {
return hitPoints;
}
public void setHitPoints(int hitPoints) {
this.hitPoints = hitPoints;
}
private int hitPoints = 3232320;
}
这没啥可说的,现在进入对应Kotlin文件
fun main{
val testJava = TestJava()
val hitPoints = testJava.hitPoints
println(hitPoints.dec())
println(hitPoints.javaClass.name)
}
运行效果
3232319
int
只要java实体类里面对应属性有get/set方法,在Kotlin这边就能直接访问以及修改对应值。
几乎没任何难度,直接看下一个!
1.2 方法访问操作
进入TestJava
public class TestJava {
private final String TAG = this.getClass().getSimpleName();
public String utterGreeting() {
return TAG + "_utterGreeting";
}
public String determineFriendShipLevel() {
return null;
}
public void javaException() throws IOException {
throw new IOException("java 异常");
}
public static int getTestInt() {
return testInt;
}
public static void setTestInt(int testInt) {
TestJava.testInt = testInt;
}
private static int testInt;
}
对应Kotlin
//定义私有扩展
private fun String?.default(default: String): String {
if (this == null) {
println("该变量为空,返回默认值")
return default
}
return this
}
fun main() {
val testJava = TestJava()
println(testJava.utterGreeting())
val level = testJava.determineFriendShipLevel()
/*
* 从 java 那边穿过来的值类型为String!,这表示可能返回 String 或者 String?
* 至于从 java 方法返回是 String 还是 null 或者其他什么的,编译器并不知道,
* 这种被称为平台类型
* 所以在使用时,一定要小心,尽量多加空操作
* */
level.default("null").toUpperCase().run(::println)
TestJava.setTestInt(11111) //测试java对应的静态方法是否能访问
println(TestJava.getTestInt())
try {
testJava.javaException()
}catch (a:Exception){
println(a.message)
}
}
运行效果
TestJava_utterGreeting
该变量为空,返回默认值
NULL
11111
java 异常
运行发现,Kotlin依然能够直接调用Java对应的方法、静态以及对应Java方的异常捕获!Java不需要做任何事
不过注意的是:在Java里,会有出现空的情况,所以在不确定对应Java对应的属性以及方法返回值是否为空的话,最好在Kotlin这边提前处理好,以免报错!
现在看完了Kotlin调用Java的,那看看Java调用Kotlin的?
2、Java调用Kotlin
2.1 Kotlin非伴生调用
先进入目标Kotlin类Spellbook.kt
class Spellbook {
fun add(num1: Int, num2: Int): Int {
return num1 + num2
}
var list = listOf("Magic Ms.L", "Lay on hans")
fun acceptApology() {
throw IOException()
}
}
对应java调用
public class TestJava {
public static void main(String[] args) {
Spellbook spellbook = new Spellbook();
int sum = spellbook.add(12, 32);
System.out.println("sum:" + sum);
ArrayList<String> listStr = new ArrayList<>();
listStr.add("hello I'm Java");
listStr.add("hello I'm Java");
System.out.println("list " + spellbook.getList());
spellbook.setList(listStr);
System.out.println("list " + spellbook.getList());
spellbook.acceptApology(); //调用Kotlin那边的自定义异常
}
}
运行效果
sum:44
list [Magic Ms.L, Lay on hans]
list [hello I'm Java, hello I'm Java]
Exception in thread "main" java.io.IOException
at Spellbook.acceptApology(Spellbook.kt:15)
at TestJava.main(TestJava.java:51)
狠简单,没啥可说的!直接下一个!
2.2 Kotlin伴生调用
先进入目标Kotlin类Spellbook.kt
class Spellbook {
companion object {
val spells = listOf("Magic Ms.L", "Lay on hans")
val MAX_SPELL_COUNT = 10
fun add(num1: Int, num2: Int): Int {
return num1 + num2
}
fun acceptApology() {
throw IOException()
}
}
}
在之前讲解里,提到过 companion object
表示对象Spellbook
对应的伴生对象。它的意思就和Java的Static类似,表示在Kotlin里,里面的元素以及对应方法可以直接通过类名.
出来。
那么看看Java是怎样调用Kotlin伴生对象里的方法与属性呢?
public class TestJava {
public static void main(String[] args) {
ArrayList<String> listStr = new ArrayList<>();
listStr.add("hello Companion I'm Java");
listStr.add("hello Companion I'm Java");
int sum = Spellbook.Companion.add(12, 12);
System.out.println(sum);
System.out.println("list " + Spellbook.Companion.getSpells());
Spellbook.Companion.setSpells(listStr);
System.out.println("list " + Spellbook.Companion.getSpells());
Spellbook.Companion.acceptApology();
}
}
运行效果
24
list [Magic Ms.L, Lay on hans]
list [hello Companion I'm Java, hello Companion I'm Java]
Exception in thread "main" java.io.IOException
at Spellbook$Companion.acceptApology(Spellbook.kt:47)
at TestJava.main(TestJava.java:63)
我们看到,通过.Companion
这个关键字来间歇性访问了Kotlin对应伴生对象里的属性和方法!那如果说,不想通过这个方法呢?有没有好的方法?
既然这样问了,那就肯定有的,重新改造对应Kotlin里的内容:
class Spellbook {
companion object {
@JvmField
val spells = listOf("Magic Ms.L", "Lay on hans")
@JvmField
val MAX_SPELL_COUNT = 10
@JvmStatic
fun add(num1: Int, num2: Int): Int {
return num1 + num2
}
@JvmStatic
@Throws(IOException::class)
fun acceptApology() {
throw IOException()
}
}
}
我们看到对应的Kotlin里面的属性以及方法都加上了对应的注解,并且acceptApology
额外加了@Throws
注解,这个注解表示java方调用这个方法必须要进行异常捕获,类似于在java方法后加了在这里插入add Throws
。
现在来看看Java使用!
public class TestJava {
public static void main(String[] args) {
ArrayList<String> listStr = new ArrayList<>();
listStr.add("hello Companion I'm Java");
listStr.add("hello Companion I'm Java");
int sum = Spellbook.add(12, 12);
System.out.println(sum);
System.out.println("list " + Spellbook.spells);
Spellbook.spells = listStr;
System.out.println("list " + Spellbook.spells);
try {
Spellbook.acceptApology(); //这里不进行try catch的话就直接报错!
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行效果
24
list [Magic Ms.L, Lay on hans]
list [hello Companion I'm Java, hello Companion I'm Java]
这里我们看到,之前的那个“中间商”没有了,现在java可以直接通过类名.
的方式直接访问对应的方法和属性了!
那是不是就这样没了?伴生与非伴生都讲完了!Kotlin还有啥Java不能调的?或者说不能完全发挥方法特性的?
Kotlin能够给方法形参赋初始值,Java调对应的方法能赋初始值么?
来试试看:
2.3 调用形参带默认值的方法
class Spellbook {
companion object {
@JvmStatic
fun getSpellbookGreeting(leftHand: String = "berries", rightHand: String = "beef") =
println("Mmmm... you hand over some delicious $leftHand and $rightHand")
}
}
fun main(){
Spellbook.getSpellbookGreeting()
}
先看看对应Kotlin运行效果:
Mmmm... you hand over some delicious berries and beef
从这个运行效果上看,当Kotlin方法里对应形参带有初始值的情况下,调用对应方法,可以不用传对应参数。那用java来调调这个方法:
如图所示
在Java使用这个方法时,却没有使用到Kotlin对应特性。想要使用那个方法只能传入两个参数。
那如果说Java就是想体验对应特性呢?
也不是不可以,现在改造一下对应Kotlin代码:
class Spellbook {
companion object {
// /*
// * 可以多个注解一起使用
// * */
@JvmStatic //表示 该方法 在java 层 可通过 static 静态访问,也可通过实例对象访问
@JvmOverloads //表示该方法 在java 层 已对该函数进行了重载,可不传,可传变量1或者两者都传
fun getSpellbookGreeting(leftHand: String = "berries", rightHand: String = "beef") =
println("Mmmm... you hand over some delicious $leftHand and $rightHand")
}
}
fun main(){
Spellbook.getSpellbookGreeting()
}
在这额外加了新的注解:@JvmOverloads
,现在回到Java试试看哇:
如图所示
到Java这边也体验到了Kotlin对应的特性。是不是很简单哇。
结束语
好了,本篇到这里就结束了!同时Kotlin对应的基础教程到这也结束了!相信看到这里的小伙伴,已经具备了Java转Kotlin的基础能力!读者也可尝试将Java项目逐步转移至Kotlin!反正它俩能够相互调用!
从下一篇开始,将会开启Kotlin进阶教程——协成!编译器也将从Idea转向我们熟悉的AS!