Java 變長參數varargs
Java類有一些方法定義時會使用不定長度的參數
public class JavaArrayExample {
public void removeIndicesVarArg(int... indices) {
// code here...
}
}
在這種情況下,需要使用擴展操作符(*
)來傳遞參數IntArray
val javaObj = JavaArrayExample()
val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndicesVarArg(*array)
目前無法給一個變長參數的函數傳遞null
操作符
Java無法對函數標記和操作,也就無法使用操作符語法。Kotlin允許使用任何Java方法(函數名和簽名正確即可)當做操作符負載operator overloads
。使用內置的語法調用Java函數是不支持的。
強制檢查異常 Checked Exception
在Kotlin中所有的異常都是非強制檢查的,編譯器不會強制要求捕獲任何異常。因此,當調用一個定義了強制檢查的異常的Java方法的時候,Kotlin不會強制你做任何事情。
fun render(list: List<*>, to: Appendable) {
for (item in list) {
to.append(item.toString()) // Java would require us to catch IOException here
}
}
對象方法
當Java類型移植到Kotlin的時候,所有java.lang.Object
類型的引用,都被轉換成Any
。 因此Any
是平臺無關的,它僅定義了toString(), hashCode() and equals()
這幾個方法,當想要使用java.lang.Object
類的其他方法時,Kotlin需要使用方法擴展
wait()/notify()
Effective Java 第69項建議使用併發工具而不使用wait()
和notify()
。因此這些方法在Any
類型的引用中並不存在。如果你真的需要調用他們,可以把他強轉成java.lang.Object
類型,再使用。
(foo as java.lang.Object).wait()
getClass()
想要獲取Java 的類對象,可以在一個類引用上調用java擴展屬性
val fooClass = foo::class.java
上面的代碼還可以使用Kotlin 1.1 中引入的新特性綁定類引用,可以使用javaClass
擴展屬性。
val fooClass = foo.javaClass
clone()
想要複寫clone()
方法,你的類必須繼承kotlin.Cloneable
class Example : Cloneable {
override fun clone(): Any { ... }
}
finalize()
想要複寫finalize()
方法,要做的就是簡單地定義它,不需要使用override
關鍵字
class C {
protected fun finalize() {
// finalization logic
}
}
根據Java規則,finalize()
不能是私有的
從Java類集成
Kotlint中的類,可以繼承最多一個Java類和任意多個接口。
訪問靜態成員
Java類的靜態成員轉換成了’companion objects’ ,不能傳遞’companion objects’,但是可以直接訪問
if (Character.isLetter(a)) {
// ...
}
Java反射
Java反射可以用在kotlin上,反過來也可以。可以通過使用instance::class.java
, ClassName::class.java
或者instance.javaClass
來使用java反射
其他支持行爲包括獲取一個Java 的getter/setter方法,或者支持一個Kotlin屬性,KProperty
對應一個Java 成員變量,KFuntion
對應一個Java方法或者構造函數,反過來也可以對應。
SAM 規範(Single Abstract Method)
和Java 8 一樣,Kotlin也支持SAM 規範。這意味着Kotlin函數可以被自動轉換成一個帶有單一默認函數的Java接口的實現,只要接口的參數類型和Kotlin函數的參數類型匹配就行。
可以這樣創建一個SAM 接口的實例
val runnable = Runnable { println("This runs in a runnable") }
在方法中調用,可以這樣
val executor = ThreadPoolExecutor()
// Java signature: void execute(Runnable command)
executor.execute { println("This runs in a thread pool") }
如果Java累有多個方法接受函數式接口,你可以通過使用一個適配函數來把一個lambda轉換成一個特定的SAM 類型,來選擇一個你需要調用的接口。哪些適配函數也可以在需要的時候被編譯器生成。
executor.execute(Runnable { println("This runs in a thread pool") })
注意,SAM 規範僅適用於接口,不適用於抽象類,甚至哪些僅包含了單一函數的抽象類。
還有要注意的是,這個特性僅是爲了Java,因爲Kotlin有合適的函數類型,自動把函數轉換成Kotlin接口的實現是不必要的,因此也沒有支持該操作。