4.1 Java语言和Kotlin语言对比(3)

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

你可能感兴趣的:(kotlin,我的第一本书,Kotlin,for,Android,Kotlin安卓开发)