ITmob-Ly
发布于 2021-12-24 / 608 阅读
0

Kotlin 笔记 001 - Kotlin 语言简介

KotlinBlog.JPG

Kotlin 是一种现代但已经成熟的编程语言,可以在 JVM(Java 虚拟机) 上运行的静态类型编程语言。它简洁、安全、可与 Java 和其他语言互操作,并提供多种方法来在多个平台之间重用代码以进行高效编程。它的一些基本特性,包括类、继承、条件语句和循环结构。

我们先来看看使 Kotlin 语言的一些主要特性:空安全、数据类、扩展函数和字符串模板。

1. 基本语法

Kotlin 的基本语法与 Java 有一些相似之处(如,定义包的方式相同)。

主要来看看它们的差异:

  • 定义函数
fun sum(a: Int, b: Int): Int {
    return a + b
}
  • 定义变量
// 只读变量是使用关键字 val 定义的。它们只能被赋值一次。
val a: Int = 1
val b = 2
val c: Int
c = 3
// 可以重新分配的变量使用 var 关键字
var x = 5
x += 1

2. 可空值和空检查

在 Kotlin 中,类型系统区分可以为空的引用(nullable references)和不能为空的引用(non-null references)。

例如,String 类型的常规变量不能为 null:

var a: String = "abc" // 默认是非空引用
a = null // Error 编译失败

要允许空值,通过 String? 将变量声明为可空字符串:

var b: String? = "abc" // 声明为可空引用
b = null // ok 正常编译

3. 字符串模板

Kotlin 语言的一个非常好的特性是可以使用字符串模板。它非常有用,因为我们不需要手动连接字符串:

var a = 1
// 在模板中使用变量的值
val s1 = "a is $a" 

a = 2
// 模板中也可以使用表达式:
val s2 = "${s1.replace("is", "was")}, but now is $a"

4. 条件语句

在 Kotlin 中,if 是一个表达式:它返回一个值。

var max = a
if (a < b) max = b

// With else
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

// As expression
val max = if (a > b) a else b

Kotlin 还有一个非常有用的 when 表达式作为高级 switch 语句

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}

5. 循环结构

在 Kotlin 中,可以使用标准的 for..in 结构来循环遍历集合:

for (item: Int in ints) {
    // ...
}

如果我们想迭代一个整数范围,我们可以使用范围结构:

请注意,此示例中在两侧的范围都包含在内。 step 参数是可选的

for (i in 1..3) {
    println(i)
} // 输出 1 2 3
for (i in 6 downTo 0 step 2) {
    println(i)
} // 输出 6 4 2 0

6. 类

Kotlin 中的类使用关键字 class 声明:

class Person { /*...*/ }
// header 和 body 都是可选的;如果类没有主体,则可以省略大括号。
class EmptyClz

Kotlin 中的类可以有一个主构造函数和一个或多个辅助构造函数。

// 主构造函数是类头的一部分,它位于类名和可选类型参数之后。
class Person constructor(firstName: String) { /*...*/ }

// 如果主构造函数没有任何注释或可见性修饰符,则可以省略`constructor`关键字:
class Person(name: String) {

}

// Kotlin 有一个简洁的语法来声明属性并从主构造函数初始化它们:
class InitOrderDemo(val name: String, var age: Int) {
    // 主构造函数不能包含任何代码。初始化代码可以放在以 init 关键字为前缀的初始化程序块中。
    init {
        println("First initializer block that prints $name")
    }
}

// 如果构造函数有注解或可见性修饰符,则构造函数关键字是必需的
class Customer public @Inject constructor(name: String) { /*...*/ }

// 如果您不希望类具有公共构造函数,声明一个具有非默认可见性的空主构造函数: 
class DontCreateMe private constructor () { /*...*/ }

7. 继承

默认情况下,Kotlin 的类是不允许扩展的,相当于 Java 中标记为 final 的类。

为了指定一个类对扩展是开放的,您将在定义类时使用 open 关键字。

open class Base(p: Int)

class Derived(p: Int) : Base(p)

我们还需将父类方法表示为 open。这样它才允许被覆盖。

open class Shape {
    open fun draw() { /*...*/ }
    fun fill() { /*...*/ }
}

class Circle() : Shape() {
    override fun draw() { /*...*/ }
}

8. 数据类/Data classes

在 Kotlin 中一个非常好的语言结构是数据类。这些类的目的是只保存数据。

data class User(val name: String, val age: Int)

// 编译器将根据声明的属性为我们创建方法 hashCode()、equals()、toString()、componentN()、copy()。

// 为数据类生成的 Component 函数可以在解构声明中使用它们:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age")

// 使用 copy 函数复制对象,允许更改其某些属性,同时保持其余属性不变:
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

9. 集合/Collections

Kotlin 中有两种类型的集合:可变的和不可变的。

// 当我们创建不可变集合时,意味着它是只读的:
val numbers = listOf(1, 2, 3, 4)

// 当我们想要创建一个可变集合时,需要使用 mutableListOf() 方法:
val mNumbers = mutableListOf(1, 2, 3)
mNumbers.add(4)
// 可变列表具有 add() 方法,因此我们可以向其附加一个元素。

还有其他类型集合的等效方法:mutableMapOf()mapOf()setOf()mutableSetOf()

10. 异常/Exceptions

Kotlin 的异常处理机制与 Java 中的机制非常相似。所有异常类都扩展了 Throwable。异常必须有一个消息、堆栈跟踪和一个可选的原因。

// 使用 throw 表达式抛出异常对象
throw Exception("exception message")

// 使用 try...catch 完成的异常的处理
try {
    // ...
}
catch (e: SomeException) {
    // ...
}
finally {
    // ...
}

Kotlin 中的每个异常都是未经检查的,这意味着编译器不会强迫我们捕获它们。

11. Lambda 表达式

在 Kotlin 中,我们可以定义 lambda 函数并将它们作为参数传递给其他函数。

让我们看看如何定义一个简单的 lambda:

val sum = { x: Int, y: Int -> x + y }

ints.filter { it > 0 }

12. 扩展函数

Kotlin 提供了使用新功能扩展类的能力,而无需从类继承或使用装饰器等设计模式。

要声明扩展函数,在函数名称前面加上被扩展的类型。下面为 MutableList 添加一个交换函数:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp
}
// 现在,您可以在任何 MutableList<Int> 上调用该函数:
val list = mutableListOf(1, 2, 3)
list.swap(0, 2)

13. Kotlin/Java 互相调用

Kotlin 的设计考虑到了与 Java 互相调用。现有的 Java 代码可以很自然地从 Kotlin 中调用,而 Kotlin 代码在 Java 中也可以很顺利地使用。

// Sample.kt 中定义定义顶层函数
package com.sample.app

fun demo(){ println("demo") }

// java 调用
public class TestJava {
    public static void main(String[] args) {
        SampleKt.demo();
    }
}

通过 @file:JvmName("类名") 告诉编译器生成的类名,Java 代码就可以直接使用指定的类名调用了。

@file:JvmName("Sample")
package com.sample.app

fun demo(){ println("demo") }

// java 调用
public class TestJava {
    public static void main(String[] args) {
        Sample.demo();
    }
}