kotlin与Java语言的交互
由于项目中混合了kotlin和java两种语言,所以有时间两种语言交互之间就有些尴尬,由于不太熟练,所以就记录一下。
1. Kotlin调用Java
1.1 kotlin调用Java集合类:
val kotlinList = listOf(1,2,4,5)
//这里使用的是Java原生的ArrayList
val javaList = ArrayList<Double>()
for(item in kotlinList){
javaList.add(item.toDouble())
}
1.2调用Java类的getter和setter方法
kotlin可以看做直接操作Java属性。
class Entity {
private String name ;
private int age ;
public void setName(String name){
this.name = name ;
}
public String getName() {
return name ;
}
}
//kotlin.kt
var p = Person()
p.name = 'steven'
p.age = 24
1.3 Java可变参数
public class Utils {
public static void print(String ...nameList) {
for(String item : nameList) {
System.out.println(item);
}
}
}
在kotlin代码中调用时:
var list = arrayOf("tom","steven","mary")
Utils.print(*list) //这里需要一个 * 号
1.4 关于Exception
Kotlin中所有的Exception都叫做Unchecked Exception,kotlin编辑器不强迫你捕获任何异常,如下面代码:
public static boolean checkFileExist(String filePath) throws IOException {
File file = new File(filePath);
FileWriter fileWriter = new FileWriter(file);
//do other things
return file.exists();
}
直接使用kotlin调用时:
Utils.checkFileExist("/user/")
结果就直接蹦了:
1.5 java.lang.Object方法使用
Java中Object有很多出生就会有的方法:
equals();
hashCode();
wait();
notify();
toString();
getClass() ;
在kotlin中要使用这些方法时,需要将kotlin中Any对象(它实现了toString(),hashCode()和equals()方法)转成Object对象,才能使用wait()和notify()方法。
val p = Person();
(p as java.lang.Object).notify();
(p as java.lang.Object).wait();
1.6 getClass()
这个用的比较多,我们获取对象的Java类,直接在类上使用Java扩展属性,它是Kotlin的反射类kotlin.reflect.KClass的扩展属性.
val clazz = Activity::class.java
//或者
val clazz = Activity.javaClass (kotlin1.1之后支持的绑定类引用)
非常普遍的例子为,我们启动一个新的Activity:
startActivity(Intent(this, LayoutActivity::class.java))
startActivity(Intent(this, LayoutActivity.javaClass))
1.7 clone()接口
kotlin中要调用覆盖java.lang.Object中的clone,需要实现kotlin.Cloneable:
class PJava : Cloneable{
override fun clone(): Any {
return super.clone()
}
}
1.8 java中存在kotlin的关键字:
//java代码
public class TextUtils {
public static boolean is(String a , String b) {
return null != a && a.equals(b);
}
}
is
是kotlin中关键字,需要调用时,需要加上''
,就像下面的:
TextUtils.`is`("1","3")
不过不用担心,因为编辑器都会给我们帮忙,可以直接帮我们生成需要的代码。
1.9 获取java的反射功能
val p = PJava()
var pClazz = p::class.java
var pClazz1 = PJava::class.java
var pClazz2 = p.javaClass
println(pClazz === pClazz1)
println(pClazz1 === pClazz2)
结果为:
true
true
表明三个对象pClazz
,pClazz1
,pClazz2
是同一个对象。
2. Java调用kotlin
2.1 Java调用Kotlin包级函数
有如下一个kt函数,路径与文件名如下:
然后通过AndoridStudio中Tools -> Kotlin -> show Kotlin byteCode, 然后点击一下Decompile装换成Java代码:
我们发现所写的StringUtils
类被转换成了StringUtilsKt.Java
对象,其中StringUtils
中所有方法都被转成了static final
类型方法,那么在java中调用可以表现为:
System.out.println(StringUtilsKt.verify("hello world"));
另外,加上@file:JvmName
注解可以将生成的java改名:
@file:JvmName("HXStringUtils")
package com.xing.java_kotlin
fun print(str:Any) {
println(str)
}
fun verify(str:Any?) : Boolean = str?.toString()!!.isNotEmpty()
结果为:
2.2 kotlin的实例字段
如果我kotlin对象中有个属性我不希望生成setter/getter方法,直接可以使用@JvmField
注解即可。
kotlin代码 | -> | java代码 |
---|---|---|
2.3 静态字段&静态方法
既然是静态的,那么需要涉及到伴生对象和命名对象,不是很懂的可以google,需要在他们的属性上添加@JvmField
,在方法上添加@JvmStatic
注解,这样就能生成Java的静态方法。
如下代码:
class KStudent {
var id:Long = 1
@JvmField
var name:String = "mary"
companion object {
var schoolName = "school name"
@JvmField
var schoolLocation = "SH"
@JvmStatic
fun printInfo() {
println("school info: $schoolLocation")
}
}
}
可以看到schoolLocation
属于伴生对象,已经添加了@JvmField
注解,而printInfo()方法也添加了 @JvmStatic
注解,我们来看一下对应生成的Java代码:
我们可以发现schoolLocation已经是public的静态属性了,而printInfo已经是静态方法了,那么我们调用时:
System.out.println(KStudent.schoolLocation);
KStudent.printInfo();
2.5 修饰符的可见性
如下表
Kotlin中修饰符 | Java中修饰符 |
---|---|
private | private |
protected | protected |
internal | public |
public | public |
2.6 kotlin中异常
在kotlin中不需要显示Exception的,也没有try catch finally关键字,异常来了就来了,kotlin管不住,像这个:
class KStudent {
companion object {
@JvmStatic
fun tryToThrow() {
var fileWriter = FileWriter(File("unknown path"))
fileWriter.write("hello world")
}
}
}
直接调用时,没有显示显示效果:
但是运行时肯定是没戏了,程序直接蹦,那么如果我们需要提示操作者这里有异常,要怎么做呢?
需要用到@Throws(Exception::class)
注解
class KStudent {
companion object {
@Throws(IOException::class)
@JvmStatic
fun tryToThrow() {
var fileWriter = FileWriter(File("unknown path"))
fileWriter.write("hello world")
}
}
}
然后在我们调用时:
此时就需要我们try…catch了。
还有其他的,在工作中用得多的,以后再记录吧。