Kotlin 初学者Java和Kotlin互操作
Posted 帅次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin 初学者Java和Kotlin互操作相关的知识,希望对你有一定的参考价值。
作者简介:CSDN博客专家、华为云·云享专家认证
系列专栏:Kotlin 初学者
五星好评:左侧点一下(网页端),移动端:https://bbs.csdn.net/topics/603956616
目录
一、Kotlin调用Java
1.1 互操作性与可空性
Java世界里所有对象都是null,当一个Kotlin函数返回String类型值,它是可空的。
建立一个 Java 类
class JavaUser
public String userInfo()
return "Java-帅次";
//返回null
public String family()
return null;
Kotlin 调用 Java 方法
fun main()
var user = JavaUser()
println(user.userInfo())//
//使用时报错:NullPointerException
// println(user.family().length)
//平台类型,可能为null
var fam = user.family()
//当fam为null时,fam?.length返回null
println(fam?.length)//null
1.2 类型映射
代码运行时,所有的映射类型都会重新映射回对应的Java类型。
Java定义属性类型
class JavaUser
public String name = "Java";
...
Kotlin 查看类型
fun main()
println(user.name.javaClass)//查看类型:class java.lang.String
1.3 属性访问
刚才使用public修饰属性,在Kotlin可以直接调用,那么我们用private呢?
Java定义属性
class JavaUser
private int age =18;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
...
Kotlin 使用
fun main()
println(user.age)
user.age = 12
println(user.age)
println(user.age.javaClass)
如果仅使用private而不设置get/set方法 Kotlin是无法调用的,当设置了get/set方法。Kotlin可以直接调用其属性,而不用调用get/set方法(默认调用get/set方法),如下图:
二、Java调用Kotlin
2.1 @JvmName
可以使用JvmName注解指定编译类的名字。
2.1.1 在KotlinUser文件中定义kotlinUserInfo()函数
package com.scc.kotlin.primary.jandk
fun kotlinUserInfo() = "来自Kotlin的招呼"
2.1.2 在JavaMain使用main方法调用Kotlin的kotlinUserInfo()函数
package com.scc.kotlin.primary.jandk;
class JavaMain
public static void main(String[] args)
System.out.println(KotlinUserKt.kotlinUserInfo());//来自Kotlin的招呼
觉得KotlinUserKt不好看,咱们给它换个名字,或者说起个别名。
2.1.3 在Kotlin文件最上方添加@JvmName
这个必须写在文件最顶部。
@file:JvmName("SCKotlin")
package com.scc.kotlin.primary.jandk
fun kotlinUserInfo() = "来自Kotlin的招呼"
2.1.4 调用@JvmName设置的名字
public static void main(String[] args)
// System.out.println(KotlinUserKt.kotlinUserInfo());//来自Kotlin的招呼
System.out.println(SCKotlin.kotlinUserInfo());//来自Kotlin的招呼
2.2 @JvmField
在Java里,不能直接访问Kotlin定义的字段(如下:name),所以必须调用getName,然而,你可以给Kotlin属性添加@JvmField注解,暴露它的支持字段给Java调用者,从而避免使用getter方法。
class KotlinSc
@JvmField
var name = "Kotlin-SC"
var age = 13
KotlinSc的name属性添加了@JvmField注解,Java可以直接调用,age属性未添加@JvmField注解,所以Java无法直接调用,当然你可以通过get/set方法调用age属性。如下图:
class JavaMain
public static void main(String[] args)
KotlinSc kotlinSc=new KotlinSc();
System.out.println(kotlinSc.name);//Kotlin-SC
2.3 @JvmStatic
对函数使用该注解,kotlin编译器将生成另一个静态方法;
对属性使用该注解,kotlin编译器将生成其他的setter和getter方法;
这个注解的作用其实就是消除Java调用Kotlin的companion object对象时不能直接调用其静态方法和属性的问题.
注意:此注解只能在companion object中使用
class KotlinSc
...
//伴生对象
companion object
var height = 178
fun evaluate() = "SC是一个学习Kotlin的小渣渣"
在kotlin中可直接使用,但是在Java中则必须
//在kotlin中可直接使用
fun main()
println(KotlinSc.height.toString().plus("CM"))//178CM
println(KotlinSc.evaluate())//SC是一个学习Kotlin的小渣渣
//在Java中则相对复杂一些。
public static void main(String[] args)
KotlinSc kotlinSc=new KotlinSc();
System.out.println(kotlinSc.Companion.getHeight()+"CM");//178CM
System.out.println(kotlinSc.Companion.evaluate());//SC是一个学习Kotlin的小渣渣
给伴生对象的函数使用@JvmStatic注解,属性还是使用
class KotlinSc
...
companion object
@JvmField
var height = 178
@JvmStatic
fun evaluate() = "SC是一个学习Kotlin的小渣渣"
Java调用添加注解的函数和属性
public static void main(String[] args)
KotlinSc kotlinSc=new KotlinSc();
System.out.println(KotlinSc.height+"CM");//178CM
System.out.println(KotlinSc.evaluate());//SC是一个学习Kotlin的小渣渣
2.4 @JvmOverloads
JvmOverloads注解协助产生Kotlin函数的重载版本。设计一个可能会暴露给Java用户使用的API时,记得使用@JvmOverloads注解,这样,无论你是Kotlin开发者还是Java开发者,都会对这个API的可靠性感到满意。
2.4.1 未使用@JvmOverloads注解
定义一个未使用@JvmOverloads注解的Kotlin函数
fun kotlinEat(bread: String = "巧克力面包", meat: String = "鸡翅")
println("$bread-搭配-$meat-美极了")
使用kotlin调用,一点问题没有,妥妥的。
fun main()
kotlinEat();//巧克力面包-搭配-鸡翅-美极了
kotlinEat("橙香面包")//橙香面包-搭配-鸡翅-美极了
kotlinEat(meat = "羊肉")//巧克力面包-搭配-羊肉-美极了
kotlinEat("奶油长杆面包","牛肉")//奶油长杆面包-搭配-牛肉-美极了
使用Java调用,仅能调用传入两个参数的方法,而不能像Kotlin那样随意调用。
2.4.2 使用@JvmOverloads注解
我们在给kotlinEat(bread: String = "巧克力面包", meat: String = "鸡翅")函数添加@JvmOverloads注解。
@JvmOverloads
fun kotlinEat(bread: String = "巧克力面包", meat: String = "鸡翅")
println("$bread-搭配-$meat-美极了")
public static void main(String[] args)
SCKotlin.kotlinEat("Java牌面包");//Java牌面包-搭配-鸡翅-美极了
为什么会这样?咱们看看:
未使用@JvmOverloads注解
使用@JvmOverloads注解,此处截图不全,两个参数的方法没截取到,感兴趣的自己去玩玩。
使用@JvmOverloads注解后强迫该函数重载,这样Java就可以进行不同场景调用了。
2.5 @Throws
使用@Throws注解,声明这个方法要检查Exception。
//这里的Throws是必须添加的,要不Java那边无法捕捉这个异常
@Throws(IOException::class)
fun kotlinEatException()
println("吃东西呛住了")
throw IOException()
编译成Java代码,如下:
public static void main(String[] args)
try
SCKotlin.kotlinEatException();//吃东西呛住了
catch (IOException e)
System.out.println(e);//java.io.IOException
e.printStackTrace();
2.6 函数类型操作
函数类型和匿名函数能提供高效的语法用于组件间的交互,是Kotlin编程语言里比较新颖的特性。
他们简洁的语法因->操作符而实现,但Java8之前的JDK版本并并不支持lambda表达式。
在Java里,Kotlin函数类型使用FunctionN这样的名字的接口来表示的,FunctionN中的N代表值参数目。这样的Function接口从Function0到Function22(23个),每一个FunctionN都包含一个invoke函数,专用于调用函数类型函数,所以,任何时候需要调一个函数类型,都用它调用invoke。
val hair = colorHair:String ->
println( "头发染成 $colorHair 即可")
val hairTwo = colorHair:String,lengthHair:Int ->
println( "头发染成$colorHair,剪至$lengthHair-厘米即可")
Function1<String, Unit> hair = SCKotlin.getHair();
hair.invoke("红色");//头发染成 红色 即可
Function2<String, Integer, Unit> hairTwo = SCKotlin.getHairTwo();
hairTwo.invoke("蓝色",8);//头发染成蓝色,剪至8-厘米即可
Function接口从Function0到Function22(23个)
以上是关于Kotlin 初学者Java和Kotlin互操作的主要内容,如果未能解决你的问题,请参考以下文章
深入kotlin - 与Java互操作:kotlin调用java
KotlinKotlin 与 Java 互操作 ① ( 变量可空性 | Kotlin 类型映射 | Kotlin 访问私有属性 | Java 调用 Kotlin 函数 )