目录 start

  1. Kotlin学习
    1. 1、基础学习
      1. 1、变量
        1. 1、申明变量和值
      2. 2、变量类型推断
      3. 3、原始字符串与模板表达式
      4. 2、流程控制语句
      5. 3、关键字
      6. 4、与Java中不同的操作符
      7. 5、异常捕获
      8. 6、Unit类型
      9. 7、Nothing类型
    2. 2、 集合类
      1. 1、List
        1. 1、创建
        2. 2、遍历
    3. 3、面向对象编程
      1. 1、类与构造器
    4. 4、Kotlin与Java互操作

目录 end|2019-10-19 17:04|


Kotlin学习

1、基础学习

1、变量

1、申明变量和值

Kotlin的变量分为可变的var和不可变的val

  • var:可写的,在生命周期中可被多次赋值

  • val:只读的,仅能一次赋值,后面就不能被重新赋值

2、变量类型推断

在Kotlin中,大部分情况不需要说明你使用对象的类型,编译器可以直接推断出它的类型。但是,类型推断不是所有的。例如,整型变量Int不能赋值Long变量

  • 使用is运算符进行类型检测
1
2
3
4
5
6
if (obj is String) {
// 在该处obj自动转换成String
println(obj::class)
result = obj.length
println(result)
}

3、原始字符串与模板表达式

  • 原始字符串:有三重引号"""分隔(与Python一样),原始字符串可以包含换行符和任何其他字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun rawString() {
val rawString = """
// 使用is进行类型检测
fun getLength(obj: Any): Int? {
var result = 0
if (obj is String) {
// 在该处obj自动转换成String
println(obj::class)
result = obj.length
println(result)
}
println(obj::class)
return result
}/n
""".trimIndent()
println(rawString)
}
  • 模板表达式:以美元符号开始
1
2
3
// 模板表达式
val s = "$rawString has ${rawString.length} characters."
println(s)

2、流程控制语句

  • If表达式

    Kotlin中的if是一个表达式,可返回一个值, 这种情况下类似于Java中的三元表达式

    1
    val max = if (a > b) a else b

    也可向传统的If表达式样使用。

    • if-else语句规则(与Java中的基本相同)

      • if后的括号不能省略,括号内的表达式的值必须为布尔值

      • 如果条件体内只有一条语句执行,那么if后面的大括号可以省略,但建议加上大括号

      • 对于给定的if,else语句是可选的,else if也是可选的

      • else和else if同时出现时,else必须出现在else if后面

      • 如果有多条else if语句同时出现,那么如果有一条else if语句的表达式测试成功,那么会忽略其他所有else if和else分支

      • 如果出现多个if,只有一个else的情况,else子句归属于内层的if语句

  • when表达式

    类似与switch-case表达式

    • 如果有多个分支需要用相同的操作,则可以将多个分支条件放在一起,用逗号分开
    1
    2
    3
    4
    5
    6
    when (obj) {
    -1, 0 -> println("-1 or 0")
    else -> {
    println("else")
    }
    }
-   也可以检测一个是否在一个区间或集合中

1
2
3
4
5
6
7
8
fun whenIn(x: Int) {
val nums = arrayOf(1, 2, 3, 21)
when (x) {
in 1..10 -> print("在1~10之中")
in nums -> print("在数组中")
!in 10..20 -> print("不在10~20中")
}
}
  • for循环

    • 格式
    1
    2
    3
    for (item in collection) {
    ...
    }
  • while循环

    while和do..while循环和Java中的类似

  • break、continue和return的使用与Java中的一致,但Kotlin中也可使用=来直接返回一个函数的值,如fun sum(a: Int, b: Int) = a + b

  • 标签

    可显示的指定标签,也可隐式的使用标签,当隐式的使用标签时,该标签与接收lambda的函数同名

  • throw表达式

    在Kotlin中throw是表达式,它的类型是特殊类型:Nothing,该类型没有值,与Java中的void的意思相同
    如果把一个throw表达式的值赋给一个变量,需要显示声明类型为Nothing。

3、关键字

  • this

基本使用方法与Java类似,指持有当前对象的引用。但如果this没有限定符,则它指的是最内层的包含他的作用域,如果想要引用其他作用域中的this则可以使用this@label标签,如事例

  • super

与Java中的super关键字类似,指持有指向其父类的引用

4、与Java中不同的操作符

  • 相等与不等操作符

    • 引用相等与不等:===!==,判断两个引用是否是指向同一对象

    • 结构相等与不等:==!=,是使用equals()进行判断

  • Elvis操作符?:

    特定是和null比较,主要用来做null安全检查, 如y = x?:0,等价于val y = if (x !=== null) x else 0
    Elvis操作符和Java中的三元条件运算符相似,但在Kotlin中没有三元条件运算符,Elvis操作符也为二元运算符

  • 扩展函数和扩展属性

    • 扩展函数,大多数情况可以在顶层定义扩展,即直接在包中定义,这样便可在这整个包中使用。如下,在String中扩展notEmpty()方法
    1
    2
    3
    4
    5
    6
    7
    fun String.notEmpty(): Boolean {
    return !this.isEmpty()
    }

    fun main(args: Array<String>) {
    "123".notEmpty()
    }
-   扩展属性,如:`val <T> List<T>.lastIndex: Int get() = size - 1`
  • 空指针安全

    • 一个非空引用不能直接赋为null

    • 若需要为空,则可以在变量的类型后面加上?声明一个变量可空,如:var s: String? = "ad"

    • 若声明了一个可空的String,然后调用length属性时,编译器将报错,这是可使用安全调用?.和非空断言调用!!., 如s?.lengths!!.length。可空变量的安全调用符y?.length等价于是Java中的y != null ? Integer.valueOf(yy.length()) : null,可空变量的断言调用y!!.length等价的Java代码为:if (y == null) { Internsics.throwNpe(); } return Integer.valueOf(y.length());

    • 如果只对非空值进行操作,那么安全调用操作符可与let一起使用,如:s?.let { println(s) }

5、异常捕获

  • Kotlin中仍然可使用try...catch捕获并处理异常

6、Unit类型

Kotlin中的Unit类型实现了与Java中的void一样的功能。不同的是,当一个函数没有返回值时,我们用Unit来表示这个特征,而不是null。
大多数情况下,我们并不需要显示地返回Unit类型,或者声明一个函数的返回类型为Unit。编译器会自动推断它

7、Nothing类型

Kotlin中没有Java和C中的类似函数灭有返回值的标记void,但是拥有一个对应的Nothing。在Java中,返回void的方法,其返回值void是无法被访问到的。

  • Unit和Noting的区别

    Unit类型表达式计算结果的返回值类型是Unit。Noting类型的表达式计算结果是永远不会被返回的。

2、 集合类

Kotlin的集合类分为:可变集合类不可变集合类, 集合类型主要分为:Listsetmap

1、List

1、创建

  • 不可变集合类List(ReadOnly, Immutable)

    使用listOf函数构建一个不可变的List

    • 使用listOf()构建一个没有元素的List, 该情况下必须指定类型
      val list: List<Int> = listOf()

    • 使用listOf创建一个只有1个元素的List
      val list_1 = listOf(1)

    • 使用listOf创建一个有多个元素的List
      val list_2 = listOf(0, 1, 2)

    • 使用arrayListOf创建一个list
      val list_3 = arrayListOf(9, 3, 4)

  • 可变集合类MutableList(Read&Write, Mutable), 与不可变的List相比,添加了add/addAll、remove/removeAll/removeAt、set、clear、retainAll等更新修改的操作

    创建可变List对象与创建不可比and额List类似,前面加上mutable

    • 使用mutableListOf创建可变的List
      val list = mutableListOf(123, 23)

    • 使用arrayListOf创建可变的List
      val list_3 = arrayListOf(9, 3, 4)

2、遍历

  • 使用Iterator迭代器

    1
    2
    3
    4
    5
    // 使用迭代器遍历
    val iterator = list.iterator()
    while (iterator.hasNext()) {
    println(iterator.next())
    }
  • 使用forEach遍历

    1
    2
    3
    list.forEach {
    println(it)
    }

    还可使用list.forEach(::println)

3、面向对象编程

1、类与构造器

Kotlin中的类与Java中类似,使用class声明

  • 构造函数

    Kotlin中,一个类可以有一个主构造函数,同时也可拥有一个或多个次构造函数

    • 主构造函数

      主构造函数是类头的一部分,直接放在类名后面, 如下所示。如果主构造函数没有任何注解或者可见性修饰符,可以省略constructor关键字,如果构造函数有注解或可见性修饰符,constructor关键词则是必须的,并且这些修饰符在它前面。主构造函数中声明的属性可以是可变的或不可变的。主构造函数不能包含任何代码。初始化的代码可以放在以init关键字作为前缀的初始化块中,如下所示

      1
      2
      3
      4
      5
      6
      7
      open class Student constructor(var name: String, var age: Int) {

      init {
      println("name is $name, and age is $age")
      }

      }
-   次构造函数

    > 在类体中,可以声明前缀有`constructor`的次构造函数,次构造函数不能有声明val或var。如下所示

    
1
2
3
4
5
6
7
8
9
10
11
class Teacher {

constructor(name: String) {

}

constructor(name: String, age: Int) {

}

}
> 如果一个非抽象类没有声明任何构造函数,他会有一个生成的不带参数的主构造函数。构造函数的可见性是public - 私有构造函数 声明如下:
1
2
class Test private constructor(){
}
  • 抽象类

    含有抽象函数的类(该类需用abstract修饰),称为抽象类

    • 抽象函数

      • 抽象函数必须用abstract关键字修饰

      • 抽象函数不能手动添加open,默认为open修饰

      • 抽象函数没有具体的实现

      • 含有抽象函数的类成为抽象类,必须有abstract关键字修饰。抽象类可以由具体实现的函数,这样的函数默认是final,如果想要重写这个函数,给这个函数加上open关键字

    • 抽象属性

      • 抽象属性在抽象类中不能被初始化

      • 如果在子类中没有主构造器,要对抽象属性手动初始化。如果子类中有主构造器函数,抽象属性可以在主构造函数中声明

  • 接口

    Kotlin的接口可以包含抽象的方法及方法的实现

    使用冒号:来实现一个接口,如果有一个多个用逗号隔开

  • 继承

    • open关键字

      当一个类使用open关键字修饰后,这样的类便可被继承。在Kotlin中若果方法需要被重写则应在方法上标注open关键字

在子类中同实现接口一样,使用冒号进行继承,
如果父类有构造函数,那么必须在子类的主构造函数laingge中进行继承,没有的话则可以选择主构造函数后二级构造函数

1
2
3
4
5
6
7
8
9
10
class ExtendClass : OpenClass() {

override fun save() {
super.save()
}
}

class ExtendClassTwo(name: String) : Base(name) {

}

4、Kotlin与Java互操作