这一部分内容了解大概就行,官方参考讲的很不清楚,实际使用中如果遇到问题再去查详细的资料
概述
Kotlin在设计时就考虑了与Java的互操作性。可以从Kotlin中自然地调用现存的Java代码,在 Java代码中也可以顺利地调用Kotlin代码。
1 在Kotlin中调用Java
Getter和Setter
遵循Java约定的getter和setter方法(名称以get开头的无参数方法和以set开头的单参数方法)在Kotlin中表示为属性。例如:
import java.util.Calendar
fun calendarDemo() {
val calendar = Calendar.getInstance()
if (calendar.firstDayOfWeek == Calendar.SUNDAY) { //会调⽤ getFirstDayOfWeek()
calendar.firstDayOfWeek = Calendar.MONDAY //会调⽤ setFirstDayOfWeek()
}
}
请注意,如果Java类中的某字段只有一个setter,它在Kotlin中并不会作为属性可见,因为Kotlin中不存在只有setter的属性。
返回void的方法
如果一个Java方法返回void,那么从Kotlin中调用时返回Unit。
Java中标识符与Kotlin关键字重名的情况
一些Kotlin关键字在Java中是合法的标识符,如in、object、is等等。比如你在Java代码中定义了一个名为is的函数,那么在Kotlin代码中你是无法直接调用该函数的,因为is会被当成kotlin中的关键字,解决办法:使用反引号将is括起来以表示该函数。
foo.`is`(bar)
空安全和平台类型
来自Java代码的对象在Kotlin中会被特别认为是平台类型(以String为例,其平台类型被表示为String!
)。平台类型对应于kotlin中的可空类型还是非空类型是不确定的,换句话说,这个需要由你根据实际来决定,一般情况下,我们会将一个平台类型的对象赋值给一个可空类型的变量,但是如果你能确定此平台类型对象不可能为null的话,也可以将其赋值给一个非空类型的变量。
举个例子:
//java文件:JavaClass.java
package cn.szx.kotlindemo
public class JavaClass {
public static String getName() {
if (new Random().nextInt(100) % 2 == 0) {
return "ZhangSan";
} else {
return null;
}
}
}
//kotlin文件:Test.kt
package cn.szx.kotlindemo
fun test() {
/**
* 调用一个返回字符串的java方法,返回值被认为是平台类型“String!”
*/
val name1: String? = JavaClass.getName()//将其赋值给一个可空类型的变量
name1?.substring(1)
val name2: String = JavaClass.getName()//如果你确信getName()的返回值不可能为null的话,也可以将其赋值给一个非空类型的变量
name2.substring(1)//如果name2为null的话,会抛出空指针异常
}
Kotlin中的Java泛型
和Java一样,Kotlin在运行时不保留泛型,即对象不携带传递到他们构造器中的那些类型参数的实际类型。即ArrayList<Integer>()
和ArrayList<Character>()
是不能区分的。这使得执行is检测不可能照顾到泛型。Kotlin只允许is-检测星投影的泛型:
if(a is List<Int>) //错误:无法检查它是否真的是⼀个Int列表
if(a is List<*>) //OK:不保证列表的内容
此外,Kotlin中的数组是不型变的,这意味着Kotlin中不允许我们把一个Array<String>
赋值给一个Array<Any>
。而在Java中,数组是协变的,即可以把一个String[]赋给一个Object[]。
受检异常
在Kotlin中,所有异常都是非受检的,这意味着编译器不会强迫你捕获或抛出异常。因此,当你调用一个可能抛出异常的Java方法时,Kotlin不会强迫你做任何事情:
fun render(list: List<*>, to: Appendable) {
for (item in list) {
to.append(item.toString()) //Java会要求我们捕获或声明抛出IOException
}
}
访问Java类的静态成员
Kotlin中没有static的概念。对于Java类中的静态成员,系统会为其生成所在类的伴生对象,我们无法将这样的“伴生对象”作为值来传递,但可以访问其成员,例如:
if (Character.isLetter(a)) {
...
}
反射
Java反射适用于Kotlin类,反之亦然。
你可以使用instance::class.java,ClassName::class.java或者instance.javaClass来获得java.lang.Class的实例,然后就可以使用Java的反射机制了。
在Kotlin中使用JNI
Kotlin中使用external关键字来声明本地方法,其他和Java中一样:
external fun foo(x: Int): Double
SAM转换
就像Java8一样,Kotlin支持SAM转换,这意味着lambda表达式可以被自动转换成只有一个方法的Java接口的实现:
view.setOnClickListener {
Log.e("Log", "view被点击了!")
}
注意,SAM转换只适用于接口,而不适用于抽象类,即使这些抽象类也只有一个抽象方法。
2 在Java中调用Kotlin
属性
Kotlin属性会编译成以下Java元素:
- 一个getter方法
- 一个 setter方法
- 一个私有字段,与属性名称相同(仅限具有幕后字段的属性)
例如,var firstName: String
会被编译成以下Java代码:
private String firstName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
包级变量和函数
即顶层变量和函数。会被编译成Java类的静态成员。如:在org.foo.bar包内的example.kt文件中声明的所有的变量和函数,都编译成名为org.foo.bar.ExampleKt的Java类的静态成员。
最后
对Kotlin官方参考的整理到这里就结束了,这只是对Kotlin的一个简单入门。要进一步深入学习Kotlin,建议看《kotlin for android developers》和《Kotlin in Action》这两本书,都是Kotlin官方所大力推荐的。