4.2 Kotlin标准库函数

欢迎前往我的CSDN
Kotlin提供了一个系统库,是Java库的增强,很多函数适配了Java的类型和方法,同时使用Kotlin的语法,下面我们来研究下广泛使用的函数。

Apply

  • apply 是 Any 的扩展函数, 因而所有类型都能调用。
  • apply 接受一个lambda表达式作为参数,并在apply调用时立即执行,apply返回原来的对象。
  • apply 主要作用是将多个初始化代码链式操作,提高代码可读性。

参考以下实例我们来分析下:

fun main(args: Array<String>) {
    val runnable  = Runnable { 
        print("is running")
    }
    val thread = Thread(runnable)

    thread.isDaemon = true
    thread.start()
}

我们用标准库函数Apply来改写代码:

fun main(args: Array<String>) {
    val runnable = Runnable {
        print("is running")
    }
    Thread(runnable).apply { isDaemon = true }.start()
}

看看代码是不是减少了不少啊,我们创建了一个Runnable实例,然后创建了一个线程运行这个实例,在闭包中我们配置线程实例为一个守护线程。闭包中的代码会在线程实例上运行,并且可以直接在返回值上调用start()方法。

let

let默认当前这个对象作为闭包的it参数,返回值是函数的最后一行或者指定return结果。
let 和 apply 类似, 唯一的不同是返回值,let返回的不是原来的对象,而是闭包里面的值。

fun main(args: Array<String>) {
    println(testLet())
}

fun testLet():Int{
    "Alfred".let {
        println(it)
        println(it.length)
        return 999  //指定返回值为999
    }
}

结果:

Alfred
6
999
fun main(args: Array<String>) {
    val name = "Alfred".let {
        println(it)
        println(it.length)
        "张三" //没指定返回值时,默认返回值为闭包的最后一行
    }

    println(name)
}

结果:

Alfred
6
张三

with

有时候我们在执行对象的多个方法时,必须要写很多次对象名,显得很啰嗦。比如:

class Persion(val name: String, val age: Int, val sex: String) {

    fun showName() {
        println(name)
    }

    fun showAge() {
        println(age)
    }

    fun showSex() {
        println(sex)
    }
}

fun main(args: Array<String>) {
    val persion = Persion("alfred",29,"男")
    persion.showName()
    persion.showSex()
    persion.showAge()
}

执行结果:

alfred
男
29

persion这个实例名是不是重复写了很多遍啊。虽然很整齐啊,但是不推崇。
下面我们使用with来简化下代码:

fun main(args: Array<String>) {
    val persion = Persion("alfred",29,"男")
    with(persion){
        showName()
        showSex()
        showAge()
    }
}

看看是不是相对来说简化了,也挺清晰易懂的。

run

run函数跟apply函数很像,只不过apply返回当前自身对象,而run返回最后一行或指定值,run 就是with与let组合。

fun main(args: Array<String>) {
    val name = "Alfred".run {
        println(this)
        println(this.length)
        "张三" //返回最后一行
    }

    println(name)
    println(testRun()) 
}

fun testRun():String{
    "Alfred".run {
        return "jack" //指定返回
    }
}

结果:

Alfred
6
张三
jack

lazy

lazy是另一个很有用的函数,可以把非常耗费资源的操作延迟到第一次调用时加载。比如:

fun main(args: Array<String>) {
    val name = lazy {
        for (i in 1..10) {
            print("# ")
        }
        "alfred"
    }

    println(name.value)
    println(name.value)
}

结果:

# # # # # # # # # # alfred
alfred

第一次调用println(name.value)时,才会初始化name,先执行for循环打印10次#,再初始化值为alfred。第二次调用println(name.value)时,name已经赋值为alfred,所以直接打印alfred。
总结: 第一次调用时,lazy 闭包会调用。一般用在单例模式。

use

use与try语句类似,实现了Closeable接口的对象可调用use函数,use函数会自动关闭调用者(无论中间是否出现异常)。下面我们看下源码:

/**
 * Executes the given [block] function on this resource and then closes it down correctly whether an exception
 * is thrown or not.
 *
 * @param block a function to process this [Closeable] resource.
 * @return the result of [block] function invoked on this resource.
 */
@InlineOnly
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        when {
            apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
            this == null -> {}
            exception == null -> close()
            else ->
                try {
                    close()
                } catch (closeException: Throwable) {
                    // cause.addSuppressed(closeException) // ignored here
                }
        }
    }
}

可以看出,use函数内部实现也是通过try-catch-finally块捕捉的方式,所以不用担心会有异常抛出导致程序退出。
close操作在finally里面执行,所以无论是正常结束还是出现异常,都能正确关闭。
看个例子:

fun main(args: Array<String>) {
val io = Files.newInputStream(Paths.get("/data/home/alfred/TestKotlin/.idea/encodings.xml"))
    val info = io.use {
        it.bufferedReader().readLines()
    }
   println(info)
}

结果:

[<?xml version="1.0" encoding="UTF-8"?>, <project version="4">,   <component name="Encoding">,     <file url="PROJECT" charset="UTF-8" />,   </component>, </project>]

use 无论如何都会将 io close, 避免了写复杂的 try-catch-finally 代码。Kotlin的IO流操作变得行云流水。

repeat

顾名思义,repeat 接受函数和整数作为参数,函数会被调用 指定 次,这个函数避免写循环。
还记得lazy初始化那个打印#的例子吗?我们把for循环改写下:

fun main(args: Array<String>) {
    val name = lazy {
        repeat(10) { print("# ") }
        "alfred"
    }

    println(name.value)
    println(name.value)
}

结果:

# # # # # # # # # # alfred
alfred

简单吧!! 语法可有抽象为:

repeat(次数) { 
    重复语句
}

require/assert/check

  • require负责检查输入的参数,如果有问题,抛出IllegalArgumentException
  • check负责检查自身是否万事俱备可以执行了,如果不是,抛出IllegalStateException
  • require + check就是在做前置条件的检查,通过了才可以执行真正的程序逻辑
  • assert负责确保程序执行完毕后的结果/内部状态是否符合预期,如果不是,抛出AssertionError

此处只列出相关知识点,有兴趣的话可以参考如下博客,写得非常详尽。
用好 Require,check,assert,写好 Kotlin 代码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342