kotlin interop with Java
Calling Java in Kotlin
Array Interoperability
Unlike java, arrays in Kotlin are non-typed, that is, Kotlin does not allow us to assign an Array to an Array.
// Kotlin
var arrayAny = arrayOf(1, "2", true)
val arrayString = arrayOf(1, 2, 3)
// arrayAny= arrayString // error, Type mismatch
// Java
String[] arrayString = new String[]{"1", "2", "3"};
Object[] arrayAny;
System.out.println(arrayAny = arrayString); //[Ljava.lang.String;@4dc63996
Check for exceptions in Java
In Kotlin, all exceptions are non-checked (Non-Checked Exception, compiler exception), which means that the editor won't force you to catch any of them, but there may be runtime exceptions, so they have to be handled anyway.
// Java中JSONObject,编译期异常
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("key1", "key");
jsonObject.get("none_key")
jsonObject.get("none_key")
} catch (JSONException e) {
e.printStackTrace();
}
// Kotlin,并没有强制。
val jsonObject = JSONObject()
jsonObject.put("key1", "key")
// 此句运行时异常,如下log。
jsonObject.get("none_key")
01-31 16:26:29.923 18281-18281/com.autodesk.shejijia.consumer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.autodesk.shejijia.consumer, PID: 18281
java.lang.RuntimeException: Unable to start activity
Caused by: org.json.JSONException: No value for none_key
at org.json.JSONObject.get(JSONObject.java:389)
at com.autodesk.shejijia.consumer.designer.project.activity.DesignerProjectActivity.initView(DesignerProjectActivity.kt:40)
at com.autodesk.shejijia.shared.framework.base.BaseActivity.onCreate(BaseActivity.java:46)
at android.app.Activity.performCreate(Activity.java:6910)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
Call Java's Object method
- getClass()
Get the Java class of the object.
“`
val product = Product()
val simpleName = product.javaClass.simpleName
val simpleName1 = product::class.java.simpleName
println(simpleName) //Product
println(simpleName1) //Product
### 关键字冲突
> 一些Kotlin的关键字是Java中的有效标识符,比如in,object、is等,使用反引号(')字符转义,一般IDE自动添加了。
Kotlin中调用:
fun main(args: Array) {
JavaDemo.is
()
}
Java中方法:
public static boolean is() {
return true;
}
### Nothing类型
>Kotlin的Nothing是一个特殊类型,在Java中没有对应的类型。在使用时Nothing参数的地方会生成一个原始类型。
Kotlin中:
fun emptyList(): List = listOf()
Java中:
List list = JavaKotlinKt.emptyList();
System.out.println(list); // []
## 在Java中调用Kotlin
###包级函数
在**package com.liuhe.kotlin**内的JavaKotlin.kt源文件中声明了所有函数和属性,包括扩展函数,都将编译成一个名为
**com.liuhe.kotlin.JavaKotlinKt**的Java类中的静态方法。
### 访问Kotlin属性
class KotlinClass {
var id: Long = -1L
var name: String = “kotlin”
var isOpen: Boolean = true
var isBig: String = “Y”
@JvmField var no = 0
}
在Java中,一般字段会映射成set/get方法,以is开头的对应的规则(以isBig为例)是setXx,isXx。
### 调用实例字段
@JvmField注解对Kotlin属性字段标注,表示这是一个实例字段(Instance Field),Kotlin在编译时,不会给此字段生成Getters/Setters方法。
### 调用静态字段和方法
class KotlinClass {
companion object {
var innerId = “x001” // private
@JvmField
var innerName = "ABC" // public
fun getClassInnerId() = "x001"
@JvmStatic
fun getClassInnerName() = "ABC"
}
}
public class JavaDemo {
public static final void main(String[] args) {
String innerId = KotlinClass.Companion.getInnerId();
// String innerId = KotlinClass.getInnerId();// error
String innerName = KotlinClass.innerName;
// String innerName = KotlinClass.Companion.getInnerName(); // error
KotlinClass.getClassInnerName(); // ok
KotlinClass.Companion.getClassInnerName(); //ok
// KotlinClass.getClassInnerId(); //error
KotlinClass.Companion.getClassInnerId(); // the only way to call
}
}
### Kotlin与Java的可见性
[可见性修饰符](https://www.kotlincn.net/docs/reference/visibility-modifiers.html)
Kotlin | Java | 备注
---|---|--
private | private |它只会在声明它的文件内可见
protected | protected |
internal | public | 它会在相同模块内随处可见
public | public |默认修饰符,意味着你的声明将随处可见
> 一个模块是编译在一起的一套 Kotlin 文件,可以认为是一个module。
Java访问权限
Kotlin | 类内部 | 本包 | 子类 | 外部包
---|---|---|---|---
public |v|v|v|v
protected|v|v|v|x
default|v|v|x|x
private|v|x|x|x
### 生成默认参数函数的重载
在kotlin中,一个函数中的参数如果设置了默认值,就可以重载调用,但是在Java中只能调用全参数的。如果在Java中也想重载调用,需要在Kotlin函数上加注解@JvmOverloads,这样编译器会针对此函数做特殊处理,生成多个重载函数。
**Kotlin中:可以重载调用**
fun f1(name: String = “name”, age: Int = 10) {}
@JvmOverloads
fun f2(name: String = “name”, age: Int = 10) {}
fun main(args: Array) {
f1()
f1(“xiaoming”)
f1(“xiaoming”, 15)
}
**Java中:未加@JvmOverloads, 只能调用全参数的**
JavaKotlinKt.f1(“xiaoming”, 12);
// JavaKotlinKt.f1(“xiaoming”); // error!!
JavaKotlinKt.f2(“xiaoming”);//ok
### 显示声明Kotlin中的异常
Kotlin中没有受检异常,比如下边定义的异常,虽然编译时未抛出异常,但是运行时候回抛异常。
object CheckKotlinException {
fun thisIsException() {
throw Exception(“I am a Exception”)
}
}
Java中调用:
public static final void main(String[] args) {
CheckKotlinException.INSTANCE.thisIsException();
}
```
Exception in thread "main" java.lang.Exception: I am a Exception
at CheckKotlinException.thisIsException(JavaKotlin.kt:39)
at JavaDemo.main(JavaDemo.java:23)
Solution: Use the annotation @Throws(Exception::class) so that the Java compiler will check for this exception.
object CheckKotlinException {
@Throws(Exception::class)
fun thisIsException() {
throw Exception("I am a Exception")
}
}
Kotlin and Java simple example comparison
- for loop
Java
for(String item : items)
for(Map.Entry<String,String> entry:map.entrySet())
Kotlin
for(item in items)
for((key,value) in map)
- traverse
Java
HashMap<Integer, String> map = new HashMap<>();
map.put(1,"One");
map.put(2,"Two");
// Java7
for (String str : lists) {
System.out.println(str);
}
// Java 8+
list.forEach(aa -> System.out.println(aa));
Kotlin
val map = mapOf(1 to "One", 2 to "Two")
listOf.forEach { println(it) }
- function definition
Java
void doSomething(int... numbers){
// 实现
}
Kotlin
fun doSomething(vararg numbers:Int){
// 实现
}