kotlin03.基础函数库

158 阅读1分钟

字符串操作

  • == 判断值相等
  • ===判断引用相等
  • subString 支持 until表达
  • replace支持lambda表达式
  • split支持分割赋值
  • forEach可以遍历字符串的每个字符
const val t1 = "hello great huya com"
const val t2 = "tik ,tok , cat ,fish"
const val t3 = "hello china"
const val t4 = "hch"
const val t5 = "hch"
var t6 =  "hch".capitalize()
const val t7 =  "Hch"

fun main() {
    var index = t1.indexOf("huya")
    println(t1.substring(0 until index))

    var (a,b,c,d) = t2.split(",")
    println("$a $b $c $d")

   var temp = t3.replace(Regex("[china]")){
        when(it.value){
            "c"->"1"
            "h"->"2"
            "i"->"3"
            "n"->"4"
            "a"->"5"
            else -> it.value

        }
    }
    println(temp)

    println(t4 == t5) //true
    println(t4 === t5) // true ,同一个字符串在内存中指向的是同一个常量地址
    println(t6 == t7) //true
    println(t6 === t7) //false

    t1.forEach { print("$it ") }
}

数字类型

image.png

  • 所有数字类型都是有符号的
  • toIntOrNull/toDoubleOrNull等安全转化函数,不会抛出异常
  • 数字格式化 %.3f, %.2l
  • double转int toInt / roundToInt
import kotlin.math.roundToInt

fun main() {
    var a = "1.11".toIntOrNull()
    println(a?.javaClass)

    var b = "%.3f"
    println(b.format(8.95678))

    println(8.95678.toInt())
    println(8.95678.roundToInt())
}

基础函数库

很多的基础函数如apply , also , let , run , with等,他们位于standard.kt文件中.

功能上具有相似性,在表现上主要有两点不同

  • 函数的函数体中传入的参数不同,一般都是this/it,it只能对参数进行处理,this能够访问调用对象的属性和方法.
  • 函数的返回值不同,有些返回的是最后一行的结果result,有些返回的是this.

区别总结如下表格

函数名入参返回值
applythisthis
alsoitthis
letitresult
runthisresult
withthisresult

关键区别分析 T.()->Unit与(T)->Unit

以also 和apply的源码分析来分析

  • 可以看出如果block的定义是T.()->Unit,则默认传入this作为block入参,如果block的定义是(T)->Unit,则传入it作为入参
  • T.()->Unit 等同于为T定义了一个基于T的无参数的扩展函数,所以在函数体内可以直接通过this或省略来访问T代表的对象
  • (T) -> Unit通过形参T可将对象作为实参传给函数,所以函数体里能通过it或者指定名称的方式来访问该对象
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

apply

  • 返回的当前的接受者对象
  • block的入参是this
  • 对对象进行多个赋值,类似于建造者模式
import java.io.File

fun main() {
    var file = File("a").apply {
        println(this.hashCode() )
        setExecutable(false)
        setReadable(true)
        setWritable(true)
    }

    println(file.hashCode())
}
// this 和 file是同一个对象

also

  • 与apply功能类似
  • block的入参是it
  • 返回this

let

  • let返回的是lambda表达式的最后一行结果result
  • let与elvis结合可以用于替换 if/else
var aInt = "hello".let { it.length + 20 }
println(aInt)

//let + elvis
fun init(input:String?):String{
    return input?.let { "$input .. hello" } ?: "unkonwn"
}

//用if /else实现的写法
fun init2(input:String?):String{
    if (input == null){
        return "unkonwn"
    }else{
        return "$input .. hello"
    }
}

run

  • 执行某个函数,且返回值为函数最后一行结果
  • 可以链式执行多个函数,每个函数输入为上一个的输出
  • 可以执行函数引用
println("I am Chinese".
    run { contains("am") }.
    run { if (this) "abc" else "def" })


println("I am Chinese".run(::contains).run (::check))

fun contains(input:String?):Boolean?{
    return input?.contains("am")
}

fun check(b:Boolean?):String{
    return "abc".takeIf { b?:false } ?: "def"
}

with

  • 与run功能类型
  • 输入第一个参数为值参,第二个为处理函数
var hello = with("hello world") {
    this.replace(Regex("[aeiou]" , )){
        when(it.value){
            "a"->"0"
            "e"->"1"
            "i"->"2"
            "o"->"3"
            "u"->"4"
            else -> it.value
        }
    }
}
println(hello)

takeIf

  • 如果takeIf中的函数的结果为true,则返回接受者,否则返回null
  • 实用与条件判断
  • 可以用于三元表达式的替换
println( File("test.txt").takeIf {
       println(it.absolutePath)
       it.exists()
   }?.readText() )
  
b.takeIf{a} ?:c

takeUnless

用法与takeIf相反