Kotlin快速入门指南

2021-07-06  本文已影响0人  小O机

本文参考Kotlin中文官网,官网写的很详细,是很好的入门参考资料。这篇文章主要是作为对官方文档的整理,不对原理做过多解释,方便新手快速入门。需要注意的是,你需要有java基础。

一、Kotlin是什么

Kotlin和java一样,是一门编程语言,运行在JVM之上,都需要经过编码——编译——执行的过程,不同的是java代码编译使用的是javac编译器,而kotlin代码使用的是kotlinc编译器。语言没有高低之分,只有使用场景和特性的区别。

二、Kotlin能做什么

kotlin完整包含java特性,所以java能做的kotlin都能做,比如服务器,Android开发。

三、实践

1、创建一个类

class MyClass {
}

这样声明的类默认是final的,无法被继承,要想开放继承,使用open修饰符

open class MyClass {
}

kotlin没有new关键字,创建对象直接使用 类名(参数)的格式

val myClass = MyClass()

1.1、构造函数

java中的构造函数

public class MyClass {
    // 无参构造器,默认。如果显式写出来,则会被带参构造器覆盖
    public MyClass() {
    }
    
    // 带参构造器
    public MyClass(String s) {
    }
}

kotlin中一个类可以有一个主构造函数和一个或者多个次构造函数。如果主构造函数没有任何注解和可见性修饰符,则可省略constructor关键字

// 主构造函数
class MyClass constructor() {
}

// 次构造函数
class MyClass {
    constructor() {
    }
}

// 没有注解和修饰符的著构造函数
class MyClass() {
}

如果有注解或者可见性修饰符,则constructor关键字不能省略,且这些注解和修饰符在它前面

// 有注解和修饰符的主构造函数不能省略constructor关键字
class MyClass private @Inject constructor() {
}

如果类有一个主构造函数,那么次级函数都要直接或间接委托给主构造函数,使用this关键字

// kotlin
class MyClass constructor() {
    constructor(s: String): this() {
    }
}

// 或者
class MyClass() {
    constructor(s: String): this() {
    }
}

如果需要在类中进行初始化,使用init关键字修饰的初始化代码块

class MyClass() {
    init {
        // init job1
    }
    
    init {
        // init job2
    }
    ...
}

初始化代码块是主构造函数的一部分,因此所有初始化代码块都会在主构造函数中优先执行,其次才会执行次构造函数中的代码。

1.2、变量

var:修饰可变量
val:修饰不可变量
成员变量可以和java一样,在类体内声明,注意此时声明变量是必须初始化(或使用lateinit关键字懒初始化)

// 必须初始化
class MyClass {
    lateinit var s1: String
    val s2: String = "S2"
}

也可以在主构造器中声明,此时可以不初始化

// 可以不初始化
class MyClass constructor(
    var s1: String,
    val s2: String = "S2"
) {    
}

// 或者
class MyClass(
    var s1: String,
    val s2: String = "S2"
) {    
}

使用类型推断,可以把类型去掉,变成

var s1 = "S1"

1.3、函数

1.3.1、具名函数

使用fun关键字声明

fun getName(): String {
    return name
}

区别于java,返回类型在函数声明后面,用:隔开,如果没有返回值,用Unit接收,可以省略不写。上面函数还可以简化为单表单表达式函数

fun getName(): String = name
// 或简化为
fun getName() = name

1.3.2、匿名函数

顾名思义就是没有名字的函数,比如下面这种写法

private fun getName() {
    // 变量name接收匿名函数,name表示一个函数,需要两个Int类型入参,返回Int
    val name: (Int, Int) -> Int = { a: Int, b: Int ->
         a+b
    }
    // 调用name函数,传入1,2作为参数,函数结果传递给value
    val value: Int = name(1, 2)
    println(value)
}

// 以上函数调用部分可以直接写成这样
{ a: Int, b: Int ->
    a+b
}(1, 2)

注意,匿名函数如果有返回值,一般不用return,函数体中最后一行的结果默认作为返回值。匿名函数只能出现在其他函数体中,不能独立存在。更多具名函数和匿名函数的介绍,参考这篇文章
Kotlin学习笔记函数篇(1)具名函数和匿名函数

1.3.3、局部函数

kotlin支持局部函数,即一个函数在另一个函数内部

fun getName(s1: String) {
    fun setName(s2: String) {
        println(s1)
    }
}

成员函数可以访问外部函数(闭包)的局部变量。

2、内部类

这部分和java基本相同,在kotlin中普通内部类(也叫嵌套类)默认是static的,不持有外部类引用,

class Outer {
    class Nested {
    }
}

使用inner关键字修饰,那么就不是static的,会持有外部类对象的引用

class Outer {
    private val s: String = "S"
    inner class Nested {
        println(s)
    }
}

匿名内部类

Android中会经常写如下代码

mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // click event
            }
        });

使用kotlin可以这样写

mView.setOnClickListener(object: View.OnClickListener {

            override fun onClick(view: View) {
                // click event
            }
        })

3、集合

3.1、构造集合

可以完全使用Java创建集合的方式,比如

val list = ArrayList<String>()
val map = HashMap<Int, String>()
val set = HashSet<String>()
val sparseArray = SparseArray<String>()

也可以使用kotlin原生库,比如

val list = arrayListOf<String>()
val map = hashMapOf<Int, String>()
val set = hashSetOf<String>()
// SparseArray没有kotlin原生构建方式
val sparseArray = SparseArray<String>()

在构造集合的同时可以初始化,

val list = arrayListOf<String>("1", "2", "3")

3.2、遍历集合

3.2.1、forEach

val list = arrayListOf<String>()
list .forEach { s ->
    println(s)
}

val map = hashMapOf<Int, String>()
map .forEach { entry ->
    println("${entry .key} -> ${entry .value}")
}

3.2.2、for

val list = arrayListOf<String>()
for (s in list) {
    println(s)
}

val map = hashMapOf<Int, String>()
for (entry in map ) {
    println("${entry.key} -> ${entry.value}")
}

3.2.3、iterator

val list = arrayListOf<String>()
val iterator = list .iterator()
while (iterator.hasNext()) {
    println(iterator.next())
}

val map = hashMapOf<Int, String>()
val iterator = map .iterator()
while (iterator.hasNext()) {
    val entry = iterator.next()
    println("${entry.key} -> ${entry.value}")
}

4、条件判断

4.1、if else

用法上kotlin基本和java一致,不同的是,koltin中if else是可以有返回值的,比如

val value = if (条件一) {
    "这是条件一的返回值"
} else {
    "这是else的返回值"
}

if else条件代码块中最后一行代码的结果会默认作为整体的返回值。另外,由于kotlin没有三目运算符,所以可以用if else来提代。

4.2、when

kotlin中的when对应java中的switch case

when (条件) {
    匹配值1 -> {
        println("这是匹配值1的结果")
    }
    匹配值2 -> {
        println("这是匹配值2的结果")
    }
    匹配值3 -> {
        println("这是匹配值3的结果")
    }
    ...
    else -> {
        println("这是没有匹配到的结果")
    }
}

同样,when也可以作为表达式来使用,返回的是条件代码块中最后一行代码的执行结果

val value = when (条件) {
    匹配值1 -> {
        "这是匹配值1的结果"
    }
    匹配值2 -> {
        "这是匹配值2的结果"
    }
    匹配值3 -> {
        "这是匹配值3的结果"
    }
    ...
    else -> {
        "这是没有匹配到的结果"
    }
}

5、空判断

kotlin中默认参数不能为null,在声明一个变量的时候需要初始化,如果定义的变量可以为null,使用?进行标识

val s: String = "S" // 必须初始化,且不能为null
var s1: String? = null // 必须初始化,但可以为null

如果一个变量在声明的时候无法初始化,但又不能为null,此时可以用lateinit来修饰,

lateinit var s3: String // 声明时不必初始化,不可null

注意,lateinit修饰的变量可以不在声明时初始化,但定要在使用前进行初始化,否则会抛异常。

6、作用域函数

作用域函数唯一的作用就是在对象的上下文中执行代码块,也就是说这个作用域指的就是对象的上下文。作用域函数一共5种:letrunwithapply 以及 also。作用域函数的详细介绍参考Kotlin学习笔记_作用域函数

上一篇 下一篇

猜你喜欢

热点阅读