Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Java-Kotlin document #849

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 127 additions & 123 deletions docs/KotlinAndJava.md
Original file line number Diff line number Diff line change
@@ -1,165 +1,198 @@
# Mirai - Kotlin And Java

本章介绍部分 Kotlin 定义对应的 Java 代码,以帮助 Java 使用者理解 Mirai 的源代码。

本章介绍部分 Kotlin 定义对应的 Java 定义,以帮助 Java 使用者理解 Mirai 的源代码
每部分中第一个代码块为 Kotlin 代码,第二个代码块为 Java 代码

每部分第一个代码块为 Kotlin 代码,第二个代码块为 Java 代码。

预计阅读时间:5 分钟
预计阅读时间:8-10 分钟

#### 通用
- Kotlin 的定义都默认是 `public` 和 `final`

- Kotlin 不需要句末分号,通常以换行作为一个语句的结束
- Kotlin 的定义在不指定的情况下默认带有 `public` 修饰符和 `final` 修饰符(如果可能)

#### `class`
```kotlin
class A
```

```java
public final class A {
}
```

#### 构造器定义

以下几种 Kotlin 定义是等价的。
- Kotlin 在构造对象时不需要 `new` 关键字。

```kotlin
class A {
private val value: String

constructor(value: String) {
this.value = value
}

constructor(integer: Int) {
this.value = integer.toString()
}
}
val a = A("test")
```

```java
A a=new A("test");
```

#### 属性

- Kotlin 内的属性有两种:`val` 和 `var`
- Kotlin 的 `val` 是不可变的,只能被赋值一次,相对应的 `var` 为可变属性,可以被多次赋值。
- 编译器为 `val` 创建 `getter`,为 `var` 创建 `getter` 和 `setter`
- 默认情况下只能通过 `getter` 和 `setter` 访问变量

```kotlin
class A(val value: String) { // 类定义后面的括号表示主构造器
constructor(integer: Int) : this(integer.toString())
class A {
var varValue: String = "test"
val valValue: String = "test"
}
```

对应的 Java 定义为:
```java
public final class A {
private final String value;

public A(String value) {
this.value = value;

private final String valValue = "test";

public String getValValue() {
return valValue;
}

public A(int integer) {
this.value = String.valueOf(integer);

private String varValue = "test";

public final String getVarValue() {
return varValue;
}

public final String setVarValue(String varValue) {
this.varValue = varValue;
}
}
```

通常 Kotlin class 都会有一个主构造器。

#### 构造器调用
#### 顶层定义和 `const`

Kotlin 不需要 `new` 关键字。
- Kotlin 可以直接在文件内定义函数和属性,可分别称为「顶层函数」和「顶层属性」,统称为「顶层定义」
- `XXX.kt` 中的顶层定义会被编译为名为 `XXXKt` 的 `class`,且带有 `static` 修饰符
- `const` 可以修饰顶层 `val` 属性或伴生对象内的 `val` 属性,编译器会把它编译为 Java 静态字段(不含有 `getter`)

```kotlin
val a = A("test")
// Test.kt
val x: String = "xx"

const val CONST_VALUE: String = "cc"

fun foo() {}
```

```java
A a = new A("test");
// TestKt.java
public final class TestKt {
public static final String CONST_VALUE = "cc"; // const val 没有 getter

private static final String x = "xx";

public static String getX() {
return x;
}

public static void foo() {
}
}
```

#### 函数
#### 静态属性

```kotlin
class A {
fun test(string: String): Int = 1
}
object Test {
val x = "x" // public String getX()
@JvmField
val y = "y" // public static final String y;
@JvmStatic
val z = "z" // public static String getZ()
}
```

```java
public final class A {
public int test(String string) {
return 1;
public final class Test {
public static final Test INSTANCE = new Test();

private Test() {
}
}

private final String x = "x"; // val

public String getX() {
return x;
}

public static final String y = "y"; // @JvmField val

private final String z = "z"; // @JvmStatic val

public static String getZ() {
return z;
}
}
```

#### 属性 `val`
- Kotlin 的 `val` 是不可变的,只能被赋值一次
- 编译器为 `val` 创建 `getter`
#### 构造器定义

以下几种 Kotlin 定义是等价的。

```kotlin
class A {
val value: String = "test"
}
```
private val value: String

```java
public final class A {
private final String value = "test";
public final String getValue() {
return value;
constructor(value: String) {
this.value = value
}

constructor(integer: Int) {
this.value = integer.toString()
}
}
```

#### 属性 `var`
- Kotlin 的 `var` 相较于 `val` 是可变的,可以被多次赋值。
- 编译器为 `var` 创建 `getter` 和 `setter`

```kotlin
class A {
var value: String = "test"
class A(val value: String) { // 类定义后面的括号表示主构造器
constructor(integer: Int) : this(integer.toString())
}
```

对应的 Java 定义为:
```java
public final class A {
private String value = "test";
public final String getValue() {
return value;
}
public final String setValue(String value) {
private final String value;

public A(String value) {
this.value = value;
}

public A(int integer) {
this.value = String.valueOf(integer);
}
}
```

#### 顶层定义和 `const`
- Kotlin 的定义不一定需要在 `class` 中,允许直接存在于文件中的「顶层函数」和「顶层属性」
- `XXX.kt` 中的顶层定义会被编译为名为 `XXXKt` 的 `class`
- 顶层定义会被编译为 `static`
- `const` 可以修饰一个属性,编译器会把它编译为 Java 静态字段。
通常 Kotlin class 都会有一个主构造器。

```kotlin
// Test.kt
val x: String = "xx"
#### 函数

const val CONST_VALUE: String = "cc"
在 Kotlin 内,函数可以直接等于一个值:

fun foo() { }
```kotlin
class A {
fun test(string: String): Int = 1
}
```

```java
// TestKt.java
public final class TestKt {
public static final String CONST_VALUE = "cc"; // const val 没有 getter

private static final String x = "xx";
public static String getX(){
return x;
public final class A {
public int test(String string) {
return 1;
}

public static void foo() { }
}
```

#### 单例对象
- Kotlin `object` 定义一个单例对象

- Kotlin 内使用 `object` 代替 `class` 来定义一个单例对象

```kotlin
object Test
Expand All @@ -173,39 +206,9 @@ public final class Test {
}
```

#### 静态

```kotlin
object Test {
val x = "x" // public String getX()
@JvmField val y = "y" // public static final String y;
@JvmStatic val z = "z" // public static String getZ()
}
```

```java
public final class Test {
public static final Test INSTANCE = new Test();
private Test() {}

private final String x = "x"; // val
public String getX() {
return x;
}

public static final String y = "y"; // @JvmField val

private final String z = "z"; // @JvmStatic val
public static String getZ() {
return z;
}
}
```


#### 静态
#### 静态函数

- Kotlin 没有 `static` 关键字,但可以通过 `@JvmStatic` 将一个函数编译为 `static`
- Kotlin 没有 `static` 关键字,但可以通过 `@JvmStatic` 将一个函数编译为 `static`

```kotlin
object Test {
Expand All @@ -227,9 +230,9 @@ public final class Test {

#### 伴生对象

- `class` 可以拥有 `companion object`
- 伴生对象内的 `@JvmField` 定义将会被编译到外部 `class`
- 伴生对象内的 `@JvmStatic` 函数以成员方法编译到伴生对象,然后以静态方法编译到外部 `class`
- `class` 可以拥有 `companion object` ,即伴生对象
- 伴生对象内的 `@JvmField` 定义将会被编译到外部 `class`
- 伴生对象内的 `@JvmStatic` 函数会以成员方法编译到伴生对象,然后以静态方法编译到外部 `class`

```kotlin
class Test {
Expand Down Expand Up @@ -278,7 +281,7 @@ public final class A {
}
```

`$completion` 参数类似于一个回调。需要熟悉 Kotlin 协程原理才能实现。为帮助 Java 用户,mirai 使用编译器插件处理 `suspend` 函数
`$completion` 参数类似于一个回调。需要熟悉 Kotlin 协程原理才能实现。为帮助 Java 用户,mirai 会使用编译器插件处理 `suspend` 函数

```kotlin
class A {
Expand All @@ -287,6 +290,7 @@ class A {
}
```

会变成
```java
public final class A {
public Object getValue(Continuation<? super String> $completion) {
Expand All @@ -300,4 +304,4 @@ public final class A {
}
```

Java 使用者可以认为 `@JvmBlockingBridge suspend fun getValue(): String` 相当于 `fun getValue(): String`。
Java 使用者可以认为带有 `@JvmBlockingBridge` 注解的 `suspend fun getValue(): String` 函数相当于 Java 内的 `public String getValue()` 函数