作者簡介:CSDN博客專家、華為云·云享專家認證
系列專欄:Kotlin 初學者
五星好評:左側點一下(網頁端),移動端:https://bbs.csdn.net/topics/603956616
目錄
一、Kotlin呼叫Java
1.1 互操作性與可空性
1.2 型別映射
1.3 屬性訪問
二、Java呼叫Kotlin
2.1 @JvmName
2.2 @JvmField
2.3 @JvmStatic
2.4 @JvmOverloads
2.4.1 未使用@JvmOverloads注解
2.4.2 使用@JvmOverloads注解
2.5 @Throws
2.6 函式型別操作
一、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個)

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/400599.html
標籤:其他
