【Kotlin】Kotlin学习总结


学而不思则罔,思而不学则殆

保留字总结

常见

Kotlin关键字说明类比java
val不可变变量final修饰
var可变变量非final修饰
when条件选择switch
for循环语句(用法多变)for
open类或者属性可被继承 (默认是不能被继承的)非final修饰的类
init构造函数结构体
constructor次构造函数
interface接口,跟java一样interface
data数据类保留字
object单例类修饰符

可见性保留字

修饰符KotlinJAVA
public所有类可见(默认)所有类可见
private本类可见本类可见
protected本类,子类可见本类,子类,同一包路径下可见
default同一包路径下可见
internal同一模块的类可见
  1. default 在java中是同一包下可以访问
  2. internal 则是同一模块下可以访问,范围要大一些

变量对比

Java基本数据类型Kotlin基本数据类型说明
intInt整型
longLong长整型
shortShort短整型
floatFloat单精度浮点型
doubleDouble双精度浮点型
booleanBoolean布尔型
charChar字符型
byteByte字节型

语法糖

//当函数只有一行时,可以直接卸载尾部,省略return关键字
fun myMax(num1: Int, num2: Int): Int = max(num1, num2)
fun myMin(num1: Int, num2: Int): Int = min(num1, num2)
fun myMax1(num1: Int, num2: Int) = max(num1, num2)
fun myMin2(num1: Int, num2: Int) = min(num1, num2)

逻辑控制

if 条件判断

可以有返回

//很直白的方式
fun myMin3(num1: Int, num2: Int): Int {
    var value = 0
    value = if (num1 < num2) {
        num1
    } else {
        num2
    }
    return value
}
//更够充当返回值
fun myMin4(num1: Int, num2: Int): Int {
    return if (num1 < num2) {
        num1
    } else {
        num2
    }
}

fun myMin5(num1: Int, num2: Int): Int {
    return if (num1 < num2) num1 else num2
}

fun myMin6(num1: Int, num2: Int) = if (num1 < num2) num1 else num2

when 条件语句

可以有返回

fun getTest(num:Number) {
    when(num){
        is Int -> println("is Int")
        is Double -> println("is Double")
        else -> println("is Else")
    }
}
fun getTest(num: Int) = when (num) {
    1 -> "A"
    2 -> "B"
    else -> "C"
}
作为返回值

for 循环语句

Kotlin总的循环语句更加灵活

val range = 0..10 //[0,10]双端闭区间
val range1 = 0 until 10 //[0,10) 左闭右开区间
    for (i in 0..10) {
        print("$i,")
    }
    //0,1,2,3,4,5,6,7,8,9,10,
    for (i in 0 until 10) {
        print("$i,")
    }
    //0,1,2,3,4,5,6,7,8,9,
    for (i in 0 until 10 step 2) { //i += 2
        print("$i,")
    }
    //0,2,4,6,8,
    for (i in 10 downTo 0) { //降序
        print("$i,")
    }
    //10,9,8,7,6,5,4,3,2,1,0,
    for (i in 10 downTo 0 step 2) {
        print("$i,")
    }
    //10,8,6,4,2,0,

面向对象

对象

新建一个对象

class Person {
    var name = ""
    var age = 0

    fun sleep(): Unit {
        println("$name is sleeping, He is $age years old")
    }
}
    val person = Person()
    person.name = "张宇"
    person.age = 18
    person.sleep()
    //张宇 is sleeping, He is 18 years old

继承

Kotlin中类默认是不可被继承的,需要添加关键字open,继承时用":" 代替java的extends

open class Person { //open关键字,标识该类可以被继承
    var name = ""
    var age = 0

    fun sleep(): Unit {
        println("$name is sleeping, He is $age years old")
    }
}

class Student : Person() { //: 表示继承
    var no = "20200630"//学号
    var grade = 12 //年级

    fun show(): Unit {
        println("$name $no $grade ,He is $age years old")
    }
}

构造函数

主构造函数

主构造函数是默认的,每个类默认都会有一个不带参数的主构造函数,跟java一样,当然也可以指定参数,在柱构造函数上

class Student(private var no: String, private var grade: Int) : Person() {
    fun show(): Unit {
        println("$name $no $grade ,He is $age years old")
    }
}
val student = Student("张宇",17)

init就是构造函数的结构体,一些初始化方法可以添加到这

class Student(private var no: String, private var grade: Int) : Person() {

    init {
        println("Student init a $no")
    }

    init {
        println("Student init b $grade")
    }

    fun show(): Unit {
        println("$name $no $grade ,He is $age years old")
    }
}

如果父类构造函数不为空,继承的时候需要指定父构造函数
添加默认值

class Student(private var no: String, private var grade: Int) : Person(name = "张宇", age = 18) {...}

添加参数,参数不能加任何val和var限定符,作用域限定在主构造函数中

class Student(name: String, age: Int, private var no: String, private var grade: Int) : Person(name, age) {...}

次构造函数

    class Student(name: String, age: Int, private var no: String, private var grade: Int) : Person(name, age) {
    constructor(name: String, age: Int) : this(name, age, "20200702", 12)
    constructor() : this("20200702", 12)
    }
    //初始化
    val student1 = Student()
    val student2 = Student("张宇", 18)
    val student3 = Student("张宇", 18, "20200702", 12)

只有次构造函数,没有主构造函数

class Student : Person {
    constructor(name: String, age: Int) : super(name, age) {} //显示调用父类构造函数super
    constructor() : this("20200702", 12) {}
}

//初始化
    val student1 = Student()
    val student2 = Student("张宇", 18)

接口

interface ICar {
    fun startUp() //启动
    fun stop() // 停车
}

实现

class Car(private val brand: String) : ICar {
    override fun startUp() {
        //TODO("Not yet implemented")
        println("$brand startUp")
    }

    override fun stop() {
        //TODO("Not yet implemented")
        println("$brand stop")
    }
}

简单使用

    val car = Car("红旗")
    val car1 = Car("长安")
    car.startUp()
    car1.startUp()
    car.stop()
    car1.stop()
    //红旗 startUp
    //长安 startUp
    //红旗 stop
    //长安 stop

接口默认实现

kotlin允许接口有默认实现,Java中JDK1.8过后也支持这个特性功能

interface ICar {
    fun startUp() {
        println("Car default startUp")
    } //启动

    fun stop() // 停车
}

class Car(private val brand: String) : ICar {
    override fun startUp() {
        //TODO("Not yet implemented")
        super.startUp()
        println("$brand startUp")
    }

    override fun stop() {
        //TODO("Not yet implemented")
        println("$brand stop")
    }
}
Car default startUp
红旗 startUp
Car default startUp
长安 startUp
红旗 stop
长安 stop

数据类与单例类

数据类 data class

在java中写一个数据类,需要各种get,set,而在kotlin中一行代码就可以

data class Card(var id: Int, var data: Date)
    val card = Card(10001, Date())
    val card1 = Card(10001, Date())
    println(card)
    println(card1)
    println("card == card1 : ${card == card1}")
    println("card === card1 : ${card === card1}")
    //Card(id=10001, data=Fri Jul 03 07:46:44 CST 2020)
    //Card(id=10001, data=Fri Jul 03 07:46:44 CST 2020)
    //card == card1 : true     值相等
    //card === card1 : false   不是同一个对象

单例类 object

单例类就是全局该类对象最多只有一个

object Singleton {
    var id = 0

    fun show(): Unit {
        println("Singleton show!")
    }
}
    println(Singleton.id)
    Singleton.id = 1
    println(Singleton.id)
    Singleton.show()
    println(Singleton)
    println(Singleton)

单例类的调用和使用相当于Java的静态类的属性和方法

0
1
Singleton show!
learning.data.Singleton@5e2de80c
learning.data.Singleton@5e2de80c

集合

List

    val list = ArrayList<String>()
    list.add("ONE")
    list.add("TWO")
    list.add("THREE")
    //java的使用习惯
    val list1 = listOf("FOUR","FIVE","SIX") //Kotlin方式,不可变集合
    val list2 = mutableListOf("FOUR","FIVE","SIX") // 可变集合
    list2.add("SEVEN")
    //访问list
    for (node in list){
        println(node)
    }
    

Set

    val set = setOf("FOUR","FIVE","SIX")//不可变set
    println(set)
    val set1 = mutableSetOf("FOUR","FIVE","SIX") //可变set
    set1.add("SEVEN")
    println(set1)

Map

    val map = mapOf("ONE" to 1, "TWO" to 2, "THREE" to 3) //不可变map
    println(map)
    val map1 = mutableMapOf("FOUR" to 5, "FIVE" to 5, "SIX" to 6) //可变map
    map1["SEVEN"] = 7
    println(map1)

Lambda

EX: 集合的函数式API
查找列表中最长的字符串

    val list = listOf("FOUR", "FIVE", "SIX", "ZhangYu", "WXF")
    println(list)
    var maxStr = "";
    for (node in list){ // 用java思想实现
        if (node.length > maxStr.length){
            maxStr = node;
        }
    }
    println(maxStr)
    //kotlin实现
    var maxL = list.maxBy { it.length}
    println("max $maxL")
[FOUR, FIVE, SIX, ZhangYu, WXF]
ZhangYu
max ZhangYu

语法结构

{参数名1:参数类型,参数名2:参数类型 -> 函数体}
最后一行自动作为Lambda表达式的返回值
现在很多Lambda的表达式都是简化后的,读者很更难理解,我们一步一步来理解

步骤1:构造lambda表达

    val lambda4 = { str: String -> str.length } //构建一个lambda的表达式
    var maxL4 = list.maxBy(lambda4) //传入lambda表达式作为入参
    println(lambda4) //打印lambda表达式
    println("max4 $maxL4")
(kotlin.String) -> kotlin.Int
max4 ZhangYu

步骤2:构造隐式lambda表达

var maxL5 = list.maxBy({ str: String -> str.length })

步骤3:
Kotlin规定,当Lambda参数为最后一个参数时,可以将Lambda表达式移到函数括号外面

var maxL6 = list.maxBy(){ str: String -> str.length }

步骤4
如果Lambda参数时函数唯一一个参数的话,还可以将函数的括号省略,其实跟闭包类似

    var maxL7 = list.maxBy{ str: String -> str.length }

步骤5:
类型推导机制,,不必声明参数类型

    var maxL8 = list.maxBy { str -> str.length }

步骤6:
Lambda参数唯一时,也不必声明参数,可以用默认it关键字代替

var maxL9 = list.maxBy { it.length }

Example:
所有字符都小写

    val list = listOf("FOUR", "FIVE", "SIX", "ZhangYu", "WXF")
    println(list)
    val lambda1 = { str: String -> str.toLowerCase() }
    var list1 = list.map(lambda1)
    var list2 = list.map({ str: String -> str.toLowerCase() })
    var list3 = list.map() { str: String -> str.toLowerCase() }
    var list4 = list.map { str: String -> str.toLowerCase()  }
    var list5 = list.map { str -> str.toLowerCase() }
    var list6 = list.map { it.toLowerCase() }
    println(list1)
    println(list2)
    println(list3)
    println(list4)
    println(list5)
    println(list6)
[FOUR, FIVE, SIX, ZhangYu, WXF]
[four, five, six, zhangyu, wxf]
[four, five, six, zhangyu, wxf]
[four, five, six, zhangyu, wxf]
[four, five, six, zhangyu, wxf]
[four, five, six, zhangyu, wxf]
[four, five, six, zhangyu, wxf]

Lambda 之 filter

过滤集合中的数据

    val list = listOf("FOUR", "FIVE", "SIX", "ZhangYu", "WXF")
    println(list)
    val lambda1 = { str: String -> str.length >= 5 }
    val lambda2 = { str: String -> str.toLowerCase() }
    var list1 = list.map(lambda1)
    var list2 = list.filter(lambda1)
    var list3 = list.filter(lambda1).map(lambda2) //组合使用
    println(list1)
    println(list2)
    println(list3)
    //[FOUR, FIVE, SIX, ZhangYu, WXF]
    //[false, false, false, true, false]
    //[ZhangYu]
    //[zhangyu]

Lambda 之any all

  1. any用户判断集合中是否至少存在一个元素满足指定条件
  2. all用户判断集合中是否所有元素满足指定条件
    val list = listOf("FOUR", "FIVE", "SIX", "ZhangYu", "WXF")
    println(list)
    val lambda1 = { str: String -> str.length >= 5 }
    val lambda2 = { str: String -> str.length <= 5 }
    val lambda3 = { str: String -> str.length <= 7 } 

    var anyResult = list.any(lambda1)  //存在一个字符串大于等于5
    var allResult = list.all(lambda2)  //所以字符创都小于等于5
    var allResult1 = list.all(lambda3) //所以字符创都小于等于7
    //anyResult=true, allResult=false, allResult1=true

Java函数式API的使用

    //step1:最全的Runnable
    Thread(object : Runnable {
        override fun run() {
            println("Running 1 ${Thread.currentThread()}")
        }
    }).start()

    //step2:优化
    Thread(Runnable {
        run() {
            println("Running 2  ${Thread.currentThread()}")
        }
    }).start()

    //step3:接口中只有一个待实现的方法,不显示重写,kotlin也能识别
    Thread(Runnable {
            println("Running 3 ${Thread.currentThread()}")
    }).start()

    //step4:
    Thread({
        println("Running 4 ${Thread.currentThread()}")
    }).start()

    //step5:接下来就跟Lambda一样
    Thread{
        println("Running 5 ${Thread.currentThread()}")
    }.start()
Running 1 Thread[Thread-0,5,main]
Running 2  Thread[Thread-1,5,main]
Running 3 Thread[Thread-2,5,main]
Running 4 Thread[Thread-3,5,main]
Running 5 Thread[Thread-4,5,main]

空指针检查

    var s: Student? = Student() //对象可以为空
    var s1: Student = Student() //对象不能为空
    s = null  //不会编译报错
    s1 = null //会编译报错
fun test1(student: Student) {
    //student不会为空
    student.sleep()  //正确的操作
    student?.sleep() //多余的操作
    student!!.sleep() //多余的操作
}
fun test(student: Student?) {
    //student可能为空
    student.sleep()  //不正确的操作,编译不通过
    student?.sleep() //正确的操作,为空就不运行
    if (student != null) { //等效student?.sleep()
        student.sleep()
    }
    
    student!!.sleep() //正确的操作,为空会强制跑出异常
}

?. 和 ?:

?. 表示如果为空,就不执行
?: 表示如果为空,就取默认的

    val str: String? = null
    println(str)
    var length = str?.length //如果为空就不执行,返回一个null
    println(length)

    var length1 = str?.length ?: 0 // 如果为空,就位默认值0
    println(length1)
null
null
0

let

let是一个函数,lambda的参数是自己

    val student = Student()
    println(student.hashCode())

    var lambda = { student1: Student ->
        student1.sleep()
        student1.hashCode() }
    student.let(lambda)
    
    student.let({ student2 ->
        student2.sleep()
        println(student2.hashCode()) })

    student.let({
        it.sleep()
        println(it.hashCode())
    })
    student.let {
        it.sleep()
        println(it.hashCode())
    }

都是同一个

1580066828
20200702 is sleeping, He is 12 years old
20200702 is sleeping, He is 12 years old
1580066828
20200702 is sleeping, He is 12 years old
1580066828
20200702 is sleeping, He is 12 years old
1580066828

let 结合?. 使用可以减少空判断

    var student: Student? = Student()
    println(student.hashCode())

    //优化1
    student?.let {
        it.sleep()
        println(it.hashCode())
    }

    student = null
    //优化2
    student?.let {
        it.sleep()
        println(it.hashCode())
    } ?: println("student is null")

参数默认值

fun test(num: Int = 20, name: String = "zhangyu"): Unit {
    println("name=$name num=$num")
}
    test() //两个参数都不传
    test(18)  //name采用默认的
    test(name = "wxf")//age采用默认的
    test(18, "wxf")
    test(name = "wxf", num = 28) //参数顺序可以随意

学习借鉴

第一行代码-第三版-郭霖著
Kotlin是Google官方推广的语言,Kotlin学习网址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值