Kotlin语法的学习笔记

Kotlin数据类型的介绍

Kotlin没有基本数据类型的包装类
var : 定义"可变"变量的关键字
val : 定义"不可变"变量的关键字(可以通过反射的方式来修改)

八大基本数据类型:

var b:Boolean = false //Boolean类型
var byte:Byte = 10//字节类型
var short:Short = 2//短整型
var int:Int = 20//整型
var long:Long = 40L//长整型
var char:Char = 'a'//字符类型
var float:Float = 1.1234567f//单精度浮点类型
var double:Double = 1.1234567//双精度浮点类型

Kotlin的自动类型推断:

  • 智能类型推断和类型转换(开发时使用)
  • Kotlin编译器会自动推断
  • Kotlin不同的数据类型之间不能相互赋值,要先转换再赋值
var a = 10
var b1 = a+10
var c = "22"

类型转换:

var i = 10
var s = "10"

var s1 = s.toInt()
var i1 = i.toString()

字符串的介绍:

val name = "萝莉\n世界第一\n卡哇伊"

原样输出字符串:

 val name2 =""" 
        ?萝莉
        世界第一
        卡哇伊
    """.trimIndent().trimMargin("?")//字符串去除空格

字符串比较:

val str1 = "abc"
val str2 = String(charArrayOf('a','b','c'))

比较值:

println(str1.equals(str2))
println(str1 == str2)

比较内存地址:

println(str1 === str2)

字符串切割:

val str3 =".萝-莉."
val result = str3.split(".","-")//切割字符串
println(result[1]+result[2])

获取前13个字符串:

val str4 = "D:/rj/谷歌浏览器下载/视频.mp4"
val result2 = str4.substring(0,13)
val result3 = str4.substring(0..12)//区间
val result4 = str4.substringBefore("谷")//把"谷"之前的截取出来
val result5 = str4.substringBeforeLast("谷")//把最后的"谷"之前的截取出来
val result6 = str4.substringAfter("谷")//把"谷"之后的截取出来
val result7 = str4.substringAfterLast("谷")//把最后的"谷"之后的截取出来

字符串的拼接:

fun createDiary(place: String): String {
    
    
    val result1 = "你真是一个"+place+"啊!"//java的方式
    val result2 = "你真是一个${place}啊!"//kotlin的方式( ${参数,函数,运算...} )
    return result2
}

.

.

Kotlin元组数据的介绍

  • 二元元组
//定义一个二元元组数据
val pair =Pair<String,Int>("萝莉",16)//等价于  val pair2 = "萝莉".to(16)
println(pair.first)//获取元组里的第一个数据
println(pair.second)//获取元组里的第二个数据
  • 三元元组
//定义一个三元元组数据
val triple = Triple<String,Int,String>("萝莉",16,"广东广州")
println(triple.first)//获取元组里的第一个数据
println(triple.second)//获取元组里的第二个数据
println(triple.third)//获取元组里的第三个数据

.

.

Kotlin空值处理的运算符(Kotlin最大的优点)

  • Int? : 表示定义可空类型
  • a!!: 表示关闭空检查(不建议开发时使用)
  • a?.toInt(): 表示空安全调用符 ( 等价于:if(str != null){str.toInt()}),返回可空类型
  • ?:值: 表示else默认返回的值

可空变量类型:

val k:Int? = null

非空判断:

val age:String =null!!

空安全调用符:

val age2 =age?.toInt()?:-1

.

.

Kotlin运算符与java一样

java的运算符

注:
Kotlin里面每一个运算符对应一个方法,可以通过重写对应的方法实现运算符重载

.

.

Kotlin的区间(Kotlin新增的数据存储类型)

  • 正向区间
//定义一个1~100的区间的三种方式
val range1 = 1..100//最常用的形式
val range2 = IntRange(1,100)
val range3 = 1.rangeTo(100)
  • 反向区间
val range001 = range1.reversed()

常见的遍历区间的方式:

//方式1
for (i in range1) {
    
    
	//i:表示区间里的每一项
    println(i)
}

//方式2
range001.forEach {
    
    
	//it:表示区间里的每一项
    println(it)
}

.

.

Kotlin的数组介绍

定义数组:

val arr1 = arrayOf("22","33")
val arr2 = arrayOf(22,33)
val arr3 = arrayOf("22",33)

注: Kotlin会根据数组赋值的数据来自动推断数组的类型

定义8种基本数据类型数组

val arr01 = IntArray(10)//等价于 new int[10]
val arr02 = BooleanArray(2)//等价于 new BooleanArray[2]
val arr03 = ByteArray(2)//等价于 new BooleanArray[2]
val arr04 = ShortArray(2)//等价于 new BooleanArray[2]
val arr05 = CharArray(2)//等价于 new BooleanArray[2]
val arr06 = FloatArray(2)//等价于 new BooleanArray[2]
val arr07 = DoubleArray(2)//等价于 new BooleanArray[2]
val arr08 = LongArray(2)//等价于 new BooleanArray[2]

修改数组里的值(于java一样)

arr1[1] = "卡哇伊"
arr1.set(0,"萝莉")

查找数组的角标(返回元素对应的角标,没有则返回-1)

 val index1=arr1.indexOf("卡哇伊")//第一个
 val index2=arr1.lastIndexOf("卡哇伊")//最后一个
 val index3 = arr1.indexOfFirst {
    
    
    it.startsWith("卡")
 }
println(index1)

常见的遍历区间的方式:

//方式1
for ((index,value) in arr1.withIndex()) {
    
    
    println("index=${index} 值=${value}")
}

//方式2
arr1.forEachIndexed {
    
     index, value ->
    println("index=${index} 值=${value}")
}

.

.

Kotlin集合的介绍

  • 可以自动扩展容量的数组----List

1. 创建只读集合

val list1 = listOf("3","1","2")

2. 可读可写

val list2 = mutableListOf("01","02","03","2","33","22","1010","01","02","33")

3. 向集合中添加元素

//参数1:添加的位置
//参数2:添加的内容
list2.add(1,"卡哇伊")

注: 不填写位置默认添加到最后,填写添加位置,原来元素在向后移动

4. 修改元素

list2[0] = "luoLi"

根据下标修改集合中的数据

5. 过滤集合中的元素

val find =list2.find {
    
     it.startsWith("03") }//找到第一个含有prefix标记的值
	
val filterList1 =list2.filter {
    
     it.startsWith("0") }//把集合中第一个字符含有prefix标记的所有元素找出来
	
val filterList2 = mutableListOf<String>()
 list2.filterTo(filterList2,{
    
    it.startsWith("0")})//把两个集合所有含有prefix标记的值,存放到另一个集合中
	
val filterList3=list2.filterIndexed {
    
     index, s -> index%2==0 }//把集合中角标为偶数的元素找出来

6.对集合中的元素排序

val sortedList1= list1.sorted()//正序排序
val sortedList2 = list1.sortedDescending()//倒序排序

//按照字段进行排序
val listTest = listOf(Person("时崎狂三",16),Person("楪祈",18),Person("牧濑红莉栖",22),Person("结城明日奈",15))
val sortedList3= listTest.sortedBy {
    
     it.age }//正序排序
val sortedList4= listTest.sortedByDescending {
    
     it.age }//倒序排序

7. 对集合中的元素分组

val groupBy =list2.groupBy {
    
    
    val first=it.substring(0,1)
    when(first){
    
    
        "0"->"0"
        else -> "其他"
    }
}

8. 拆分集合中的元素

val partition =list2.partition {
    
     it.startsWith("0") }
println(partition.first)
println(partition.second)

9. 求集合中的最值

val max= list1.max()//最大
val min= list1.min()//最小
val max2= listTest.maxBy {
    
     it.age }//字符比较
val min2=listTest.minBy {
    
     it.age }//字符比较

10. 去除集合中的重复元素

val set = list2.toSet()
val myList1=list2.distinct()
val myList2=list2.distinctBy {
    
     it.substring(0,1) }

11. 集合重新组合

val nameList= listTest.map {
    
     it.name }

12. 集合中某元素相加

val age=listTest.sumBy {
    
     it.age }

13. 遍历集合中的元素

 nameList.forEach {
    
    
    println(it)
}
  • 元素不重复的数组----Set( HashSet )

1. 创建只读集合

val set1 = setOf("1","2","3","3")

2. 可读可写

val set2 = mutableSetOf("01","02","03")

3. 遍历集合

treeSet.forEach {
    
    
    println(it)
}
  • 通过复杂对象来查找另一个对象的关联数组----Map

1. 创建只读集合

val map1 = mapOf("中国" to "China","英国" to "England","美国" to "USA")

2. 可读可写

val map2 = mutableMapOf()

3. 遍历集合

//遍历key
val key=map1.keys
key.forEach {
    
     println(it) }
//遍历值
val values = map1.values
values.forEach {
    
     println(it) }
//遍历键值对
map1.forEach {
    
     (k, v) ->
    println("key=${k},value=${v}")
}

.

.

Kotlin的条件判断和循环语句的介绍

  • 条件判断语句

if-else语句

fun Judge(a: Int,b:Int): Int {
    
    
    
//也支持java if的用法,但不支持三元算符---C=A>B ? 100 :200;

    return if (a>b)a else b
}

Kotlin没有switch语句,when语句(类似于switch)

fun toDo(age:Int){
    
    
    return when(age){
    
    
		//in:表示在什么里面
		//is: 表示如果是什么就怎样
        1,2,3,4,5,6-> println("没有上上小学")
        in 7..11-> println("正在上小学")
        in 12..14->{
    
    
            return println("正在上中学")
        }
        in 15..17->{
    
    
            println("正在上高中学")
        }
        in 18..21->{
    
    
            println("正在上高大学")
        }
        else ->{
    
    
            println("正在上社会大学")
        }
    }
}
  • 循环语句

for-in

注: Kotlin可以遍历字符串,Java不行

val str = "abcd"
//(c in str):表示遍历str里的每一个元素c
//step:步长
for (c in str) {
    
    
   if (c=='卡'){
    
    
       break//跳出整个循环
       // continue//跳出这次循环
   }
    println(c)
}

//打印角标
for ((index,c) in str.withIndex()) {
    
    
    println("index=${index}c=${c}")
}

forEach(高级for循环)

注: 无法使用break和continue

val str = "abcd"
    str.forEach {
    
    
        println(it)
    }

  //打印角标
    str.forEachIndexed {
    
     index, c ->
        println("index=${index}c=${c}")
    }

多层循环

注: 可以通过添加“ tag@ ” 来跳出某个循环

val str1 = "123"
val str2 = "abc"
tag@for (c1 in str1) {
    
    
    tag2@for (c2 in str2) {
    
    
        if (c1=='b'&& c2=='2'){
    
    
            break@tag2
       }
        println("${c1}${c2}")
    }
}

while和do-while

var a = 0
while (a<=100){
    
    
    println(a)
    a++
}

do {
    
    
    println(a)
    a++
}while (a<100)

.

.

Kotlin函数/方法的介绍

函数的定义

  • 无参无返回
fun Myfun(){
    
    
    println("你好!")
}
  • 有参无返回
fun Myfun(name:String,age:Int){
    
    
    println(name)
    println(age)
}
  • 无参有返回
fun getNum():Int{
    
    
    return 1
}
  • 有参有返回
fun Myfun(name:String):Int{
    
    
    return name.length
}

支持函数嵌套

fun Father(){
    
    

    fun Child1(){
    
    
        println("Child-1")
    }

    fun Child2(){
    
    
        println("Child-2")
    }
    Child1()//调用方法
    Child2()//调用方法
}

函数体只有一行代码,可以省略return,返回值类型也不用写

fun add(a:Int,b:Int) = a+b

默认参数,和具名参数(对应java的方法的重载)

  • 默认参数
fun sendRequest(path:String,method:String="GET"){
    
    
	println("请求路径=${path},请求的类型=${method}")
}

//调用方法
sendRequest(method="GET",path="www.com")//具名参数;特点:不用在意参数的位置
  • 可变参数(vararg关键字修饰可变参数)
//vararg a: Int----对应的类型是一个数组
fun jiaFa(vararg a: Int): Int{
    
    
    var result = 0
    a.forEach {
    
    
        result+=it
    }
    return result
}

泛型函数声明

/*
*  <T> :定义泛型
* (thing:T):使用泛型
*/
fun <T> parseType(thing:T): T? {
    
    
    when(thing){
    
    
        is Int->{
    
     println("是Int类型")}
        is String->{
    
     println("是String类型")}
        else->{
    
     println("不知道什么类型类型")}
    }
    return null
}

中缀表达式(可以自定义操作符)

使用infix关键字,作用:让代码更加简洁易懂
使用条件 : 1.必须成员函数或扩展函数 2.必须只有一个参数 3.参数不能是可变参数或者默认参数

class Test{
    
    
    infix fun sayHelloTo(name: String){
    
    

    }
}

扩展函数(取代java的util类)

如: 对String类的IsEmpty()进行重写

/*
* 1.对String类扩展:fun String.函数名
* 2.扩展函数可以访问当前对象里面的字段和方法
* 3.相当于把myIsEmpty方法写入到String类中,但String类的子类不能复写这个方法
* */
fun String?.myIsEmpty():Boolean{
    
    
    //this:表示当前对象
    return this==null|| this.length==0
}

高阶函数(函数作为另一个函数的参数)

fun cacl(a:Int,b:Int,block:(Int,Int)->Int):Int{
    
    
    return block(a,b)
}

//调用方法
var ab1 = cacl(10,10){
    
     a, b -> a+b }//引用私有方法
println(ab1)

补充:
使用场景 :可以处理函数变量为空的情况下调用

   val add = ::函数名//获取函数的引用
   add.invoke(1010,10)//通过引用调用函数

lambda表达式

注: 返回值是最后一行

val add:(Int,Int)->Int = {
    
    a,b -> a+b}

//调用匿名函数
println(add(20, 20))

Kotlin内置函数let、also、with、run、apply

.

.

Kotlin类的介绍

注: Kotlin中没有new关键字,使用初始化对象的时候不需要使用new

例如:
val myClass =FatherClass("萝莉",16,"123456")//定义一个对象并初始化

类的定义

注: kotlin的类都是final(私有)的,不能被继承,不能别外部调用

//open关键字:把类或者变量设置为public(公用)
open class FatherClass(){
    
    //构造函数

    var name =""
        private set//作用:禁止外部调用set方法,变为私有方法

    var age =1
        private set(value) {
    
    //给方法设置访问权限
            if (value<150){
    
    
                field = value
            }
        }

    open var phone = ""
    
	//次构造函数(类似于java的方法重载)
    constructor(name:String,age:Int):this(){
    
    
        this.name=name
        this.age=age
    }
    constructor(name:String,age:Int,phone:String):this(name,age){
    
    
        this.phone=phone
    }


    //构造函数的逻辑写在init里
/*
      init {
        ...
        }
     */

	/*--------自定义功能的函数---------*/
    open fun greeting(){
    
    
        println("卡哇伊")
    }

    private fun add(){
    
    
        println("add")
    }

}

等价于

class FatherClass(var name:String,var age:Int){
    
    //构造函数

     //次构造函数(类似于java的方法重载)
    constructor(name:String,age:Int,phonc:String):this(name,age)

	/*--------自定义功能的函数---------*/
    fun greeting(){
    
    
        println("卡哇伊")
    }
}

.

类的继承

注: 父类必须使用open关键字修饰才能被继承

class childClass:FatherClass(){
    
    
    //继承属性
    override var phone: String = "123456789"

    override fun greeting() {
    
    
		//super.greeting()//表示调用父类的方法
        println("萝莉卡哇伊")
    }
}

.

抽象类

抽象类的继承不需要open关键字,但里抽象类里的实现方法可以使用open关键字;抽象类里可以没有抽象方法和抽象属性;Java中抽象类不能有具体的方法实现

  • 定义抽象类
abstract class Human{
    
    
    abstract var color:String
    abstract var language:String

    //定义抽象方法
    abstract fun eat()

    open fun sleep(){
    
    

    }
}
  • 抽象类可以继承抽象类,并且是单继承
abstract class Human2:Human(){
    
    
    open fun sleep2(){
    
    }
}
  • 抽象类的使用(只能继承一个抽象类,可以继承多个接口)
class ZhHuman: Human2(),RideBike,DriveCar {
    
    
    override var num: String ="2233"

    //给抽象类里的抽象属性赋值
    override var color: String = "黄色"
    override var language: String = "中文"

    //实现抽象类里的抽象方法
    override fun eat() {
    
    
        println("使用筷子吃饭")
    }

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

    //实现接口里的方法
    override fun ride() {
    
    
        println("学会了骑自行车")
    }

    override fun drive() {
    
    
        println("学会了开车了")
    }
}

.

嵌套类和内部类

  • 嵌套类
class OutClass{
    
    
    var name01 = "22"

    class myClass{
    
    
        fun sayHello(){
    
    

        }
    }
}
  • 内部类(inner关键字)
class OutClass2{
    
    
    var name1 = "22"

    inner class myClass{
    
    
        var name2 = ""
        fun sayHello(){
    
    
            name2=this@OutClass2.name1
        }
    }
}

.

泛型类

泛型的作用:放任何类型,可以限制存放的类型

定义泛型类

//定义泛型类
/*
*  <T> :定义泛型
* (thing:T):使用泛型
* <T:Fruit>:泛型上限
*/
open class Box<T>(var thing:T){
    
    
}

泛型类的使用

//定义抽象类
abstract class Fruit

//定义子类的时候使用泛型(继承泛型类)
class FruitBox(thing: Fruit):Box<Fruit>(thing)

//定义子类的时候不知道具体的类型,继续使用泛型(泛型类继承泛型类)
class SonBox<T>(thing: T):Box<T>(thing)

//泛型上限, 泛型只能是Fruit类型或者Fruit类型的子类
class SonBox2<T:Fruit>(thing: T):Box<T>(thing)

//使用泛型类
val box =Box<String,Int>("22")
println(box.thing)

泛型擦除

泛型擦除:在运行的时候编译器会把设置好的泛型的类型给擦除掉

//使用inline和reified关键字,类取消泛型擦除
inline fun <reified T>getType(thing: T){
    
    
    var name = T::class.java.name//获取泛型的类型
    println(name)
}

泛型类型投射

//泛型类型投射(就可以接受Fruit类型。即Fruit的子类的类型)
//使用out关键字,作用:接受当前类型或者子类,相当于java的 <? extends Fruit>
//使用in关键字,作用:接受当前类型或者子类或当前类型的父类,相当于java的 <? super Fruit>
fun setFruitList1(list:ArrayList<out Fruit>){
    
    
    println(list.size)
}
fun setFruitList2(list:ArrayList<in Fruit>){
    
    
    println(list.size)
}

//泛型的*号投射(可以接受任何类型)相当于java的<?>
fun setFruitList3(list:ArrayList<*>){
    
    
    println(list.size)
}

.

枚举类(与java一样)

定义枚举类

enum class test02{
    
    
    type1,
    type2,
    type3,
}

枚举类的使用

test02.type1//使用枚举

//遍历枚举里的元素
test02.values().forEach {
    
    
    println(it)
}

.

数据类(相当于java的bean类)

作用: 只保存数据,没有其他任何逻辑操作,对应java的bean类

定义数据类

data class NewsData(var title:String,var desc:String,var imgPath:String,var content:String)

数据类的使用

val news = News("标题","简介","图片路径","内容")//等于val (title,desc,imgPath,content) = News("标题","简介","图片路径","内容")

println(news.title)//等于news.component1()
println(news.desc)

.

.

Kotlin接口的介绍

注:

  • Kotlin接口里面字段不能实现
  • Java接口里的方法不能实现,Kotlin可以

定义一个接口

interface RideBike{
    
    
    fun ride()//定义没有实现的方法
}

interface DriveCar{
    
    
    //权限
    var num:String
    fun drive()//定义没有实现的方法

    fun add(){
    
    
        println("33")
    }
}

.

.

Kotlin的协程的介绍

添加协程的依赖库:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0'

协程的使用

  • 使用launch关键字启动协程
suspend fun main(args: Array<String>)= coroutineScope {
    
    
    //launch启动协程(无返回值)
    val job=launch{
    
    

        //取消协程(关闭协程)
        withTimeout(10000){
    
    
            MyTask()//任务内容
        }
    }
    //job.cancel()//取消协程(关闭协程)
    //job.isActive//判断协程是否活跃状态
    //job.join()//串行执行
}

补充:

  • launch是一个函数 协程需要通过launch函数启动
  • launch前三个参数都是默认参数 参数值可以不指定
  • 最后一个参数是函数类型 调用的时候通过lambda表达式接收
  • launch函数的返回值是Job类型 就是协程的任务
  • 协程参数:
  • context: 协程上下文(协程执行的代码放在哪个 线程 或 线程池 里执行)
  • start:状态
  • async启动协程(有返回值)
suspend fun main(args: Array<String>)= coroutineScope {
    
    
		val job2 = async {
    
     MyTask2() }
		
		//获取协程的返回值
		job2.await()//通过await()可以获取协程执行完返回的数据
}

定义挂起函数

注:

  • 挂起函数:可以被挂起执行;到时间之后从线程池中空闲的线程中恢复执行
  • 挂起函数必须通过suspend进行修饰

注意 :挂起函数必须在协程中执行 或者 在其他挂起函数中执行

suspend fun MyTask(){
    
    
    println("协程执行前的线程名:${Thread.currentThread().name}")

    (1..10).forEach{
    
    
        println("${it}")
        delay(1000)//等待sleep() 非阻塞//挂起函数
    }

    println("协程执执行后的线程名:${Thread.currentThread().name}")

}

suspend fun MyTask2():String{
    
    

    delay(1000)

    return "MyTask2的返回值"
}

参考资料:

.

.

Kotlin实现单例模式

//object单例中使用字段都是静态,方法不是静态的
//缺点:里面的字段都是静态的,占内存
object  Utils{
    
    

    var name02 = "萝莉"
    var age = 10

    fun getName(){
    
    
        println(name02)
    }
}

实现与java类似的单例

class  Utils2 private constructor(){
    
    //使用构造方法 --- private constructor()

    var name02 = "萝莉"
	
	//伴生对象(需要在class中使用)
	//作用:把属性设置为静态
    companion object{
    
    
	        var age0 = 20
	    }

    companion object{
    
    
        var age = 20
        val instance:Utils2 by lazy {
    
     Utils2() }//作用:懒加载,只加载一次,是线程安全的
    }

    fun getName(){
    
    
        println(name02)
    }
}

补充:

懒加载(使用 by lazy 关键字)

条件: 必须是val修饰,返回值是最后一行代码,并且是线程安全的
特点: 使用的时候再初始化,并且只初始化一次

val name0:String by lazy {
    
     "萝莉" }

延迟加载(使用lateinit关键字)

条件: 必须是var修饰
特点: 使用前一定要先赋值,再使用

lateinit var name00:String

猜你喜欢

转载自blog.csdn.net/weixin_42324979/article/details/109776010