- 避免 kotlin 關(guān)鍵字
- 平臺(tái)類型與空值
- 異常檢查
- 調(diào)用 Java 函數(shù)式接口
??混合編程包含兩個(gè)方面:Kotlin 調(diào)用 Java 和 Java 調(diào)用 Kotlin扶镀。
避免 kotlin 關(guān)鍵字
??因?yàn)?Kotlin 出現(xiàn)的比 Java 要晚許多尊沸,所以在 Java 程序員在給 Java 標(biāo)識(shí)符命名時(shí)并沒有考慮到哪些是 Kotlin 的關(guān)鍵字滔吠。但在 Kotlin 中調(diào)用這樣的 Java 代碼時(shí),則需要將這些關(guān)鍵字用 反引號(hào)(`)
括起來七冲。例如 Java 標(biāo)準(zhǔn)輸出流 System.in
亲配,如果在 Kotlin 中調(diào)用則需要表示為 System.`in`
蔓涧。
// JavaClass.java
public class JavaClass {
public static JavaClass object = new JavaClass();
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
// main.kt
fun main(args: Array<String>?) {
val obj = JavaClass.`object`
println(obj)
}
// 運(yùn)行結(jié)果:
JavaClass
Process finished with exit code 0
平臺(tái)類型與空值
??前面提到過 平臺(tái)類型构灸,這些類型在 Java 中聲明了一個(gè)變量或者返回值蚪拦,它的類型可能為空,也可能非空冻押。Kotlin 在調(diào)用它們時(shí)會(huì)放棄類型檢查。
// Person.java
public class Person {
private String name = "小三";
private int age = 20;
private Date birthDate; // 未初始化盛嘿,為空值 null
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}
// mian.kt
fun main(args: Array<String>?) {
val person = Person()
val date = person.birthDate // 1?? 編譯器自動(dòng)推導(dǎo)洛巢,為平臺(tái)類型
println("date = $date")
val date1: Date? = person.birthDate // 指定類型Date?,可為空類型
println("date1 = $date1")
val date2: Date = person.birthDate // 2??指定類型Date次兆,不能為空稿茉。
println("date2 = $date2")
}
// 運(yùn)行結(jié)果
date = null
date1 = null
Exception in thread "main" java.lang.IllegalStateException: person.birthDate must not be null
at cn.ak.kotmodule.WwwwKt.main(wwww.kt:21)
??上面編寫了一個(gè) Java 類 Person
,它的 birthDate
字段沒有初始化所以為空值。在 Kotlin 中通過屬性訪問 Java 中的 setter
或 getter
函數(shù)漓库,代碼第1??行讀取 birthDate
屬性賦值給變量 date
恃慧,此時(shí) date
的類型是由編譯器自動(dòng)推導(dǎo)出來的,所以 IntelliJ IDEA IDE 表示的平臺(tái)類型是 Date!
渺蒿,它可以接收空值痢士。
??但是如果明確指定返回值類型,可以使用 Date?
或 Date
茂装。由于 Date?
是可空類型怠蹂,date1
可以接收空值,而 date2
是非空類型少态,不能接收空值城侧,因此代碼第2??行會(huì)發(fā)生異常。
我們將上面 mian.kt
反編譯回 Java 文件會(huì)是什么樣子彼妻?
public static final void main(@Nullable String[] args) {
Person person = new Person();
// 賦值嫌佑,但未對(duì)date空值檢查
Date date = person.getBirthDate();
String var3 = "date = " + date;
boolean var4 = false;
System.out.println(var3);
// 賦值,但未對(duì)date1空值檢查
Date date1 = person.getBirthDate();
String var8 = "date1 = " + date1;
boolean var5 = false;
System.out.println(var8);
// 臨時(shí)獲取birthDate值存儲(chǔ)在臨時(shí)變量var10000中
Date var10000 = person.getBirthDate();
// 如果var10000這個(gè)臨時(shí)變量是空值侨歉,拋出異常
Intrinsics.checkExpressionValueIsNotNull(var10000, "person.birthDate");
// 使用var10000值對(duì) date2 初始化
Date date2 = var10000;
String var10 = "date2 = " + date2;
boolean var6 = false;
System.out.println(var10);
}
??從反編譯后的代碼可以看出屋摇,date
和 date1
都沒有做空值的檢查,只有 date2
通過代碼 Intrinsics.checkExpressionValueIsNotNull(var10000, "person.birthDate");
檢查了空值为肮,并且是空值會(huì)拋出異常摊册。
異常檢查
??Kotlin 和 Java 在異常檢查上有很大的不同,Java 有受檢查異常颊艳,而 Kotlin 中沒有受檢查異常茅特。那么當(dāng) Kotlin 調(diào)用 Java 中的一個(gè)函數(shù)時(shí),這個(gè)函數(shù)聲明拋出異常棋枕,那么 Kotlin 會(huì)如何處理白修?
fun main(args: Array<String>?) {
try {
InputStreamReader(System.`in`).use { isr -> // 1??
BufferedReader(isr).use { reader -> // 2??
val command = reader.readLine() // 3??
println(command)
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
??代碼第1??行~第3??行是通過 Java 標(biāo)準(zhǔn)輸入流從鍵盤讀取字符串,相當(dāng)于 Kotlin 中的 readLine()
函數(shù)重斑。這里創(chuàng)建了兩個(gè)輸入流代碼兵睛,見代碼第1??行和第2??行。一個(gè)讀取數(shù)據(jù)的函數(shù)見代碼第3??行窥浪,它們都會(huì)拋出 IOException
異常祖很。IOException
在 Java 中是受檢查異常,必須要進(jìn)行捕獲或拋出處理漾脂,而 Kotlin 中不用必須捕獲假颇。
調(diào)用 Java 函數(shù)式接口
??Java 函數(shù)式接口中 只有一個(gè)抽象函數(shù)
的 接口
,簡(jiǎn)稱 SAM (Single Abstract Method)骨稿,在 Kotlin 中調(diào)用 Java 函數(shù)式接口非常簡(jiǎn)單笨鸡,形式是 接口名{...}
姜钳。
// Calculable.java
public interface Calculable {
int calculateInt(int a, int b);
}
// main.kt
fun main(args: Array<String>?) {
val n1 = 10
val n2 = 5
// 實(shí)現(xiàn)加法計(jì)算的Calculable對(duì)象
val f1 = Calculable { a, b -> a + b }
// 實(shí)現(xiàn)減法計(jì)算的Calculable對(duì)象
val f2 = Calculable { a, b -> a - b }
// 調(diào)用calculateInt函數(shù)進(jìn)行加法計(jì)算
println("$n1 + $n2 = ${f1.calculateInt(n1, n2)}")
// 調(diào)用calculateInt函數(shù)進(jìn)行減法計(jì)算
println("$n1 - $n2 = ${f2.calculateInt(n1, n2)}")
}
// 運(yùn)行結(jié)果
10 + 5 = 15
10 - 5 = 5
Process finished with exit code 0