Kotlin study notes (5) - kotlin and Java interoperability

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

  1. 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中的有效标识符,比如inobjectis等,使用反引号(')字符转义,一般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

  1. 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)
  1. 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) }
  1. function definition

Java

void doSomething(int... numbers){
    // 实现
}

Kotlin

fun doSomething(vararg numbers:Int){
    // 实现   
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324845318&siteId=291194637