Android开发——kotlin语法基础

目录

Kotlin的跨平台特性

声明变量和内置数据类型

 数据类型

getter和setter

循环语句

Lambda表达式(匿名函数)

it关键字

简略写法

具名函数引用 (::)

闭包

继承

无主构造

Null 安全

安全调用操作符 ( ?. )

let函数

非空断言操作符 ( !!. )

空合并操作符 ( ?: )

异常

自定义异常

先决条件函数

String

substring()

split()

replace()

标准库函数

Apply

run

With


Kotlin的跨平台特性

        Java跨平台的实现是通过JVM生成二进制字节码并且,并通过各个平台特质的JVM运行,而Kotlin 可以编译成 Jvm 字节码运行在 Java 虚拟机上,也可以编译成 JavaScript 运行在浏览器、Node 等 JavaScript 环境中,甚至可以编译成机器码,直接运行在机器本地环境中

声明变量和内置数据类型

var 和 val :  

                var是可变变量(可读可写),val是可读变量(只能读)

 声明变量格式:

              var/val 变量名 [:数据类型]  =  值

注:(有初始值时,中括号中可省略,kotlin会进行类型推导)

 数据类型

                

getter和setter

Kotlin中getter 和 setter 都是可选,只需控制变量修饰符,比如:

val不允许设置setter函数,因为它是只读的。

循环语句

Kotlin有两种循环方式,while和for-in,while与java中的while没有区别,for-in是对Java for-each的加强,Kotlin舍弃了for-i的写法,for-in需借助区间来使用

其中

  1. unitl关键字实现左闭右开
  2. step关键字实现跳步
  3. downTo关键字实现降序循环

Lambda表达式(匿名函数)

定义时不取名字的函数,匿名函数通常整体传递给其他函数,或者从其他函数返回,对kotlin很重要,有了它就可以根据需要制定特殊规则,轻松定制标准库里的内置函数

fun main() {
  val totalS  = "Mississippi".count { letter -> letter == 's' }
  println(totalS)
}

函数类型和隐式返回

kotlin中匿名函数也有类型,匿名函数可以当做变量赋值给函数类型变量,就像其他变量一样,匿名函数就可以在代码里传递了,变量有类型,变量可以等于函数,函数也会有类型,函数的类型,由传入参数和返回值决定,匿名函数也可以进行类型推断

和具名函数不同,除了极少数情况下,匿名函数不需要return关键字返回数据,匿名函数会隐式或自动返回函数体最后一行语句的结果

var blessingFun ={name:String,year:Int->
  val holiday = "New Year"
  "$name,$year,$holiday"
}

it关键字

定义只有一个参数的匿名函数时,可以使用it关键字来表示参数名,当参数大于一个时it不能使用

如上代码可以替换成

var blessingFun :(String)->String={
  val holiday = "New Year"
  "$it,$holiday"
}

简略写法

如果一个函数的lambda参数排在最后,或者是唯一的参数,name括住lambda值参的一对圆括号就可以省略

fun main() {
    //简略写法
    show("coke"){goods:String,num:Int ->  
        val currentYear = 2027
        "${currentYear}年,双11${goods}促销倒计时${num}小时"
    }//这个{}中的代码其实是参数
}
//具名函数 参数为匿名函数
private fun show (goods:String,getDiscountWords :(String,Int)->String){
    val num = (0..24).shuffled().last()//.shuffled()打乱 .last()取最后
    println(getDiscountWords(goods,num))
}

运行结果:

具名函数引用 ::

要把函数作为参数传给其他函数使用,除了传lambda表达式,kotlin还提供了其他方法,传递函数引用,函数引用可以把一个具名函数转换成一个值参,使用lambda表达式的地方都可以使用函数引用

闭包

在Kotlin中,匿名函数能修改并引用定义在自己的作用域之外的变量,匿名函数引用这定义自身的函数里的变量,kotlin中的Lambda就是闭包

能接收函数或者返回函数的函数又叫做高级函数,高级函数广泛应用于函数式编程当中

//函数类型作为返回值
fun main() {
    val getDiscountWords : (String)->String = configDiscountWords()
    println(getDiscountWords("牙膏"))
}

fun configDiscountWords():(String)->String{
    //局部变量
    val num = (0..24).shuffled().last()
    val currentYear = 2027
    return {
        "${currentYear}年,双11${it}促销倒计时${num}小时"
    }
}

继承

Kotlin中继承使用  “ : ” 连接父类,后接父类的构造 父类需使用open关键字修饰 如下

先调用父类init在调用子类init,类似于java中的初始化代码块static{},但是init{}是在构建对象时执行

无主构造

若类不使用主构造,则后续继承类也不需要使用构造,即可去掉继承类的(),次构造可以调用父类构造super进行初始化,但是次构造的参数在其他地方无法引用

Null 安全

在Java中空指针异常经常出现,而kotlin对其进行了可空性改良,采用在类型后加?来进行null的赋值管理,不加不能赋null值,例:

安全调用操作符 ( ?. )

kotlin区分可空类型和非空类型,所以如果让一个可空类型变量运行,而他又有可能不存在,针对这种潜在危险,Kotlin不允许在可空类型值上直接调用函数,采用在变量后加?.调用,例:

编译器见到有安全调用操作符,所以它知道如何检查null值。如果遇到null值,它就跳过函数调用,而不是返回null值,这种写法可以实现链式调用

Kotlin
str = str?.uppercase().plus("is great")//链式调用,后面的调用可以不加?,前方已经判断

let函数

安全调用允许在可空类型上调用函数,但是如果还想做点额外的事,比如创建新值,或者判断不为null就调用其他函数,就可以使用带let函数的安全调用操作符,可以在任何类型上调用let函数,它的主要作用是可以在指定作用域内定义一个或多个变量

fun main() {
    var str:String? = null
    var str1:String? = "butterfly"
    var str2:String? = ""
    println(judge(str))
    println(judge(str1))
    println(judge(str2))
}
fun judge(str : String?): String? {
    //安全调用操作符
    return str?.let{
        //非空白的字符串
        if (it.isNotBlank()){
            it.uppercase()
        }else{
            "not null"
        }
    }
}

运行结果:

非空断言操作符 !!.

?.是当变量为null时不会调用匿名函数,而如果一定想调用就需要非空断言操作符,!!.又称感叹号操作符,当变量值为null时,会抛出异常

Kotlin
println(str!!.uppercase())

空合并操作符 ?:

?:操作符的意思是,如果左边的求值结果为null,就直接使用右边的结果值,它也可以和let函数一起使用来代替  if/else 语句

var str:String? = null
var strWithSafe:String = str ?: "HelloWord" //基础用法
//代替  if/else
fun main (){
    var str :String? = null
    str = str?.let{
        it.uppercase()
    } ?: "HelloWord"
}

异常

异常的继承关系和try/catch写法与Java中无差别

Kotlin
fun main() {
    var number:Int? = null
    try {
        number!!.plus(1)
    } catch (e: Exception) {
        println("
操作不当")
    }
}

自定义异常

Kotlin
fun main() {
    var number:Int? = null
    checkException(number)
}
fun checkException(number: Int?){
    number ?: throw UnskillledException()
}
class UnskillledException() :IllegalArgumentException("
操作不当")

先决条件函数

kotlin标准库提供的便利函数,使用这些内置函数,可以抛出带自定义信息的异常,这些便利函数又叫做先决条件函数,可以用它定义先决条件,条件必须满足,目标代码才能执行

  • checkNotNull:如果参数为null,则抛出IllegalStateException,否则返回非null值
  • require:如果参数为false,则抛出IllegalArgumentException
  • requireNotNull:如果参数为null,则抛出IllegalStateException,否则返回非null值
  • error:如果参数为null,则抛出IllegalStateException并且输出错误信息,否则返回非null值
  • assert:如果参数为false,则抛出AssertError,并打上断言编译器标记

Kotlin
fun checkException(number: Int?){
//    number ?: throw UnskillledException()
    checkNotNull(number){
        "something is not good"
    }
}

String

substring()

字符串截取函数,与Java区别在于Kotlin中支持IntRange类型(表示一个整数范围的类型)的参数,until创建的范围不包括上限值(左闭右开)

Kotlin
fun main() {
    var index :Int = STR.indexOf('!') //
取第一个!的下标
    var newStr =STR.substring(0 until index)
    println(newStr)
}

split()

split函数返回值与Java一样为List集合数据,Kotlin中List集合又支持解构语法特性,它允许在一个表达式中给多个变量赋值,解构常用来简化变量的赋值

Kotlin
//字符串分割,
var split = STR.split('!')
println(split)
//解构(一次性给多个变量赋值)
var (origin,dest,proxy) = STR.split("!")
println("$origin$dest$proxy")

replace()

字符串替换函数比Java中的更加强大,它可以传入一个匿名函数,从而配合when操作所有符合条件的字符

Kotlin
var str1 = "the Oracle Technology Network License Agreement for Oracle Java SE."
var str2 = str1.replace(Regex("[abcde]")){
    when(it.value){
        "a" -> "1"
        "b" -> "2"
        "c" -> "3"
        "d" -> "4"
        "e" -> "5"
        else -> it.value
    }
}
println("
替换前$str1")
println("替换后$str2")

标准库函数

Apply

apply函数可看做一个配置函数,可以传入一个接收者,然后调用一系列函数来配置它以便使用,如果提供lambda给apply函数执行,它会返回配置好的接收者

Kotlin
fun main() {
    //
配置一个File实例
    val file1 = File("D:/workspace/test.txt")
    file1.setExecutable(false)
    file1.setWritable(true)
    file1.setReadable(true)
    //使用apply
    val file2 = File("D:/workspace/test2.txt").apply {
        setExecutable(false)
        setWritable(true)
        setReadable(true)
    }
}

在调用一个个函数类配置接收者时,变量名就省略掉了,这是因为,在lambda表达式里,apply能让每个配置函数都作用于接收者,这种行为有时又叫做相关作用域,因为lambda表达式里的所有函数都是针对接收者的,或者说,它们是针对接收者的隐式调用

run

与applay不同的是,run函数不返回接收者,run返回的是lambda的结果

Kotlin
fun main() {
    var file = File("D:/workspace/test.txt")
    var result = file.run {
        //
读整个文件 contains("gread")判断文本中是否有“gread”
        readText().contains("gread")
    }
    println(result)
}

run函数也可以执行具名函数引用( :: )

fun main{
    val str = "fdsafdsafa"
    println(str.run(::islong).run (::printLine)) //链式引用
}
fun islong(str:String):Boolean{
    return str.length>=10
}
fun printLine(isLong:Boolean):String{
    return if (isLong){
        "str is toLong"
    }else{
        "is gerat"
    }      
}

With

with函数是run的变体,他们的功能和行为是一样的,但with的调用方式不同,调用with时需要值参作为其第一个参数传入

Kotlin
 val str = "fdsafdsafa"
 str=with(str){     //with
写法
    if (this.length>10){
   
    "str is toLong"
    }else{
   
    "is great"
    }
}

猜你喜欢

转载自blog.csdn.net/yb941693493/article/details/127722329