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接口的实现是不必要的,因此也没有支持该操作。