关于Kotlin语法,你只需要这一篇就够了!

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情

1. GitHub地址

https://github.com/ddnosh/weekly-sample-kotlin

2. Kotlin Grammar

fun main(args: Array<String>) {
    
    
    println("this is my first kotlin.")
    /*
    1. val:常量; var:变量
     */
    val name = "Jack"
//    name = "Rose" //报错

    var age = 18
    age = 20;

    //也可明确类型
    var count: Int = 100

    /*
    2. 换行: 1. \n; 2. """ +|
     */
    val line = "here is one line\nthis is another line"
    println(line)

    val newLine = """here is one newLine
        |here is another newLine""".trimMargin()
    println(newLine)

    /*
    3. 字符串模板、占位符:$
     */
    var template = "this is a template string called $name and length is ${
      
      name.length}"
    println(template)

    /*
    4. null: ? ?. ?: !!
     */
    var nullableString1: String? = "abc" //?可为空, 不加?则不能为空
    var nullableString2: String? = null
    println(nullableString1?.length)//?.如果为空则返回null, 不为空则返回实际值
    println(nullableString2?.length)
    println(nullableString2?.length ?: "i am null")//?:如果为空则用:后面的赋值
//    println(nullableString2!!.length)//!!如果为空则强制抛异常
    var nameNullable: String? = null
    var len = nameNullable?.length
    println(len == null)

    /*
    5. 延迟初始化: lateinit var, by lazy
     */
    lateinit var lateInitByLateinit: String//lateinit var只能用来修饰类属性, 不能用来修饰局部变量和基本类型
    fun testLateInit() {
    
    
        lateInitByLateinit = "this is a lateinit string"
    }
    testLateInit()
    println(lateInitByLateinit)
    //by lazy用来修饰val变量, 可以用来修饰局部变量和基本类型,等下一次调用到的时候才会进行初始化
    val lazyByLazy: String by lazy {
    
    
        println("here is lazy init")
        "Zoo"
    }
    println(lazyByLazy)//lazyByLazy被调用到了,开始初始化,执行println("here is lazy init"),并且赋值"Zoo"

    /*
    6. is 判断类型
     */
    val isString: String? = "kotlin"
    if (isString is String) {
    
    
        println("it's string")
    }

    /*
    7. as 类型转换
     */
    val y: Int? = 123;
    val x: String? = y as? String;
    println(x);

    /*
    8. 方法
     */
    //step1: 标准写法
    fun method1(name: String): String {
    
    
        return "hello $name"
    }

    //step2: 如果返回值类型可以由编译器推断出来,则可以省略返回值类型
    fun method2(name: String) = {
    
    
        "hello $name"
    }

    //step3: 函数只有单个表达式,则可以省略花括号,直接写在=后
    fun method3(name: String) = "hello $name"

    //step4: 具有代码块的函数,必须显示指明返回类型
    fun method4(): Int {
    
    
        println("this is 100")
        return 100
    }

    println(method1("kotlin1"))
    println(method2("kotlin2"))
    println(method3("kotlin3"))
    println(method4())

    //void返回类型
    fun testVoid(): Unit {
    
    //Unit = java's void
        println("this is a void fun")
    }

    fun testVoidWithoutUnit() {
    
    
        println("this is a void fun without unit")
    }

    fun methodWithMultipleArgs(vararg name: String) {
    
    //多个参数
        println("params size is ${
      
      name.size}")
    }
    methodWithMultipleArgs("aaron")
    methodWithMultipleArgs("aaron", "beyond")

    fun methodWithOneLine(age: Int): Boolean = age == 20
    println(methodWithOneLine(20))

    //@JvmStatic and @JvmField
    println(JvmClass.name);

    //方法入参可以指定默认值
    fun sayHello(who: String = "Jerry", msg: String = "Hello") {
    
    
        println("$who - said - $msg")
    }
    sayHello()

    /*
    9.1 Class
     */
    //open表示此类可以被继承, 用在函数上面表示此函数可以被重写
    open class KotlinClass(val name: String) {
    
    
        open fun print(content: String?) {
    
    
            println(this.name + content)
        }
    }

    val kotlinClass = KotlinClass("Charles")
    kotlinClass.print(" say: hello")

    /*
    9.2 Class extends Class and Implements interface
     */
    class SubKotlinClass(name: String) : KotlinClass(name), CallBack {
    
     //父类构造函数直接赋值, 不再调用super
        override fun getName(id: Int) {
    
    
            println("id = $id")
        }

        override fun print(content: String?) {
    
    
            println(this.name + content + "!!!")
        }
    }

    val subKotlinClass = SubKotlinClass("Sub")
    subKotlinClass.print(" say: hello")

    /*
    9.3 Class with primary constructor, 主构造器定义在类头部, 因此需要init空间做初始化
     */
    class KotlinClassConstructor1 constructor(name: String) {
    
    
        val name: String

        init {
    
    
            this.name = name
        }
    }

    val kotlinClassConstructor1 = KotlinClassConstructor1("Jack")
    println("kotlinClassConstructor:${
      
      kotlinClassConstructor1.name}")

    /*
    9.4 Class with primary constructor, 主构造器定义在类头部, 也可以在类的属性初始化声明处
     */
    class KotlinClassConstructor2 constructor(name: String) {
    
    
        val prop: String = name.toUpperCase()
    }

    /*
    9.5 Class with primary constructor, 如果主构造函数没有注解或可见性说明,则 constructor 关键字可以省略
     */
    class KotlinClassConstructor3(name: String) {
    
    

    }

    /*
    9.6 Class with primary constructor, 声明属性并在主构造函数中初始化更简洁的写法
     */
    class KotlinClassConstructor4(var name: String) {
    
    

    }

    val kotlinClassConstructor4 = KotlinClassConstructor4("Jack")
    println("kotlinClassConstructor:${
      
      kotlinClassConstructor4.name}")
    /*
    9.7 Class with secondary constructor, 次级构造器, 可以有多个
     */
    class KotlinClassSecondaryConstructor {
    
    
        private var name: String
        private var age: Int = 0
        private var male: Boolean = false

        constructor(name: String) {
    
    
            this.name = name;
        }

        constructor(name: String, age: Int) {
    
    
            this.name = name
            this.age = age
        }

        constructor(name: String, age: Int, male: Boolean) : this(name, age) {
    
    
            this.name = name
            this.age = age
            this.male = male
        }

        fun print() {
    
    
            println(this.name)
        }
    }

    val kotlinClassSecondaryConstructor1 = KotlinClassSecondaryConstructor("Michael")
    kotlinClassSecondaryConstructor1.print()
    val kotlinClassSecondaryConstructor2 = KotlinClassSecondaryConstructor("Michael", 18, true)
    kotlinClassSecondaryConstructor2.print()

    /*
    9.8 class without body
     */
    class withoutBody

    /*
    9.9 DataClass
     */
    data class DataClassSample(val x: Int, val y: Int)

    val data = DataClassSample(100, 200)
    println(data.x + data.y)

    /*
    10.1 ArrayList and for
     */
    val names = arrayListOf<String>("dog", "cat")
    for (name in names) {
    
    
        println("names contains:$name")
    }

    for (i in 0 until names.size) {
    
    //从0一直到names.size - 1, 方便数组遍历而设计
        println("[for until]names contans:${
      
      names[i]}")
    }

    /*
    10.2 Map
     */
    val ages = mapOf<String, Int>("a" to 1, "b" to 2)
    for ((key, value) in ages) {
    
    
        println("$key -> $value")
    }

    /*
    10.3 可变数组
     */
    val bags = mutableListOf(1, 2, 3)
    bags.add(4)
    println(bags.last())
    println(bags[0])

    /*
    10.4 while
     */
    var cnt: Int = 0;
    while (cnt < 5) {
    
    
        println(cnt++)
    }

    if (cnt == 5)
        println("cnt = 5")

    /*
    10.5 when: 等价于switch
     */
    var a = 1
    val b = 2;
    val c = 3

    when (b) {
    
    
        1 -> println("the result is 1")
        2 -> {
    
    
            a = 11
            println(a)
        }
        1, 2 -> println("1 or 2")
        in 1..2 -> println("in 1 and 2")
        else -> {
    
    
            println("nothing")
        }
    }
    /*
    10.6 单例
     */
    println(Utils1.label)
    println(Utils2.hello())
    /*
    10.7 static
     */
    println(CompanionTest.name)
    println(CompanionTest.run())
    /*
    10.8 getter and setter
     */
    val getterAndsetter = KotlinGetterAndSetter()
    getterAndsetter.x = 100
    println("getter and setter:" + getterAndsetter.x)
    //getter and setter 二次赋值
    val person = Person()
    println("name:${
      
      person.name}")
    person.name = "hello world"
    println("name:${
      
      person.name}")
    person.age = -1
    println("name:${
      
      person.age}")

    /* 11. 内联函数
                apply	            let	                run	                with	            also
    函数体对象	this	            it	                this	            this	            it
    对象是否可省	可	                不可	            可	                可	                不可
    返回值	    必有,当前对象	    最后一行,可有可无   	最后一行,可有可无	    最后一行,可有可无	    必有,当前对象
    可否判空	    可以	            可以	            可以	            不可以	            可以
    */
    //let -> 闭包内使用it作为当前这个对象的参数; 返回值是函数最后一行, 或者return语句
    fun letTest(): Int {
    
    
        // fun <T, R> T.let(f: (T) -> R): R { f(this)}
        "letTest".let {
    
    
            println(it)
            return 1
        }
    }
    println(letTest())
    //apply -> 闭包内可以任意调用此对象; 并且最终也会返回此对象
    fun applyTest() {
    
    
        // fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
        ArrayList<String>().apply {
    
    
            add("applyTest")
            println("this = $this, size = $size")
        }.let {
    
     println(it) }
    }
    applyTest()
    //  apply with null and nonnull
    val strJim: String? = null
    strJim?.apply {
    
    
        println("apply with nonnull")
    } ?: strJim.apply {
    
    
        println("apply with null")
    }
    //with -> 闭包内可以任意调用此对象; 返回值是函数最后一行, 或者return语句
    fun withTest() {
    
    
        // fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
        with(ArrayList<String>()) {
    
    
            add("withTest")
            println("this = $this, size = $size")
        }.let {
    
     println(it) }
    }
    withTest()
    //run -> run只接收一个lambda函数为参数; 返回值是函数最后一行, 或者return语句
    fun runTest() {
    
    
        // fun <T, R> T.run(f: T.() -> R): R = f()
        "runTest".run {
    
    
            println("this = " + this)
        }.let {
    
     println(it) }
    }
    runTest()
    //run用来判空
    val s = null
    s?.run {
    
    

    } ?: run {
    
    
        println("use run to identify null")
    }
    //also
    fun alsoTest() {
    
    
        val car = Car("Benz")
        car.also {
    
    
            it.name = "BMW"
        }
        println("car's name is ${
      
      car.name}")
    }
    alsoTest()
    /*
    12. 其它
     */
    //test anonymous inner class about interface
    callback.getName(123)
    //@JvmOverloads, 声明多个参数的构造函数
    val animal = Animal()
    animal.func("dog")
    animal.func("dog", 2)
    animal.func("dog", 2, "New York")
    //lambda表达式
    val lambdaTest1 = LambdaTest1()
    lambdaTest1.setTheCallBack(object : CallBack {
    
    
        override fun getName(id: Int) {
    
    
            println("getName")
        }
    })
    //if the callback defined in java
    lambdaTest1.setTheCallBackFromJava(CallBackFromJava {
    
    
        println("getName")
    })
    val lambdaTest2 = LambdaTest2()
    lambdaTest2.setCallBack({
    
     id -> println("getName") })
    lambdaTest2.setCallBack {
    
     id -> println("getName") }
    lambdaTest2.setCallBack {
    
     println("getName") }
    //lambda使用下划线_, 没有用到的就用_代替
    val aa = mapOf(1 to "a", 2 to "B")
    aa.forEach {
    
     (_, value) -> println("value:$value") }
    // chain use
    var list = arrayOf("java", "c++", "Android", "Kotlin", "iOS")
    list.map {
    
    
        "Hello $it"
    }.filter {
    
    
        !it.contains("c")
    }.forEach {
    
    
        println(it)
    }
}

//new a interface
private val callback = object : CallBack {
    
    
    override fun getName(id: Int) {
    
    
        println("CallBack -> getName")
    }
}

/*
Object: 单例, Object修饰的类为静态类, 里面的方法和变量都是静态的
 */
object Utils1 {
    
    
    val label: String
        get() {
    
    
            if (true)
                return "here is singleton fun"
            else
                return ""
        }
}

object Utils2 {
    
    
    fun hello() {
    
    
        println("here is an object demo")
    }
}

/*
Interface
*/
//interface CallBack {
    
    
//    fun getName(id: Int)
//}

interface CallBack2 {
    
    
    fun getName(id: Int)

    fun getVersion() = 1 // can offer non-abstract method
}

/*
companion object:伴生对象,相当于java中的static
*/
class CompanionTest {
    
    
    companion object {
    
     //一个类中只能存在一个伴生对象
        val name: String = "Vincent"
        fun run() {
    
    
            println("I am running!")
        }
    }
}

/*
getter and setter: 自带, 默认隐藏
 */
class KotlinGetterAndSetter {
    
    
    var x: Int = 0
        set(value) {
    
    
            field = value
        }
        get() = field
}

class Person {
    
    
    var name: String = "Tom"
        set(value) {
    
    
            field = value
        }
        get() = field.toUpperCase()

    var age: Int = 100
        set(value) {
    
    
            if (value < 0) {
    
    
                field = 0
            } else {
    
    
                field = value
            }
        }
        get() = field
}

/*
@JvmStatic and @JvmField,主要是方便java调用,不用再在java中写.INSTANCE调用kotlin代码
*/
open class JvmClass {
    
    
    companion object {
    
    
        @JvmField
        val name: String = "jvm test"

        @JvmStatic
        fun method() {
    
    
            println("call method")
        }
    }
}

class Animal {
    
    
    //define multiple constructor
    @JvmOverloads
    fun func(a: String, b: Int = 0, c: String = "abc") {
    
    
    }
}

class Car(var name: String) {
    
    

}

class LambdaTest1 {
    
    
    var callback: CallBack? = null
    var callbackfromjava: CallBackFromJava<Any>? = null
    fun setTheCallBack(callback: CallBack) {
    
    
        this.callback = callback
    }

    fun setTheCallBackFromJava(callbackfromjava: CallBackFromJava<Any>) {
    
    
        this.callbackfromjava = callbackfromjava
    }
}

class LambdaTest2 {
    
    
    lateinit var callback: (CallBack) -> Unit
    fun setCallBack(callback: (CallBack) -> Unit) {
    
    
        this.callback = callback
    }
}

class User(var name: String, var age: Int) {
    
    

}

3. Kotlin Advanced

fun main(args: Array<String>) {
    
    

    /*
    1. lambda表达式
     */
    //(1) kotlin中lambda表达式定义在{}中
    //(2) 其参数(如果存在)在 -> 之前声明(参数类型可以省略)
    //(3) 函数体(如果存在)在 -> 后面

    //源代码:无参
    fun l1() {
    
    
        println("无参数")
    }
    //lambda表达式: 以值的形式传递
    val l1 = {
    
     println("无参数") }
    //调用
    l1()
    //源代码:有参
    fun l2(x: Int, y: String) {
    
    
        println(y.length + x)
    }
    //lambda表达式: 以值的形式传递
    val l2 = {
    
     x: Int, y: String -> println(y.length + x) }
    //调用
    l2(1, "Mike")
    //lambda表达式可以直接通过run运行
    run {
    
     l2(1, "tom") }

    //lambda简化过程
    val people = listOf(User("张三", 18), User("李四", 20))
    //1.1 函数只有lambda一个实参
    //原始完整代码
    println("年纪最大:" + people.maxBy({
    
     user: User -> user.age }))
    //step1:如果lambda表达式是函数调用的最后一个实参,它可以放在括号外面
    println("年纪最大:" + people.maxBy() {
    
     user: User -> user.age })
    //step2: 当lambda是函数唯一的实参时,可以去掉函数调用的括号
    println("年纪最大:" + people.maxBy {
    
     user: User -> user.age })
    //step3:如果lambda的参数的类型可以推导,那么可以省略参数的类型
    println("年纪最大:" + people.maxBy {
    
     user -> user.age })
    //step4:对于lambda中一个参数时,可以使用默认参数名称it来代替命名参数,并且lambda的参数列表可以简化,省略参数列表和->
    println("年纪最大:" + people.maxBy {
    
     it.age })
    //1.2 函数有除了lambda外多个实参
    fun lambdaTest1(a: Int, b: (String) -> String) {
    
    
        println("$a + ${
      
      b(a.toString())}")
    }

    fun lambdaTest2(b: (String) -> String, a: Int) {
    
    
        println("$a + ${
      
      b(a.toString())}")
    }

    lambdaTest1(11) {
    
    
        "hello: $it"
    }

    lambdaTest2({
    
     "hello: $it" }, 22)

    //定义匿名函数,赋值给test变量
    var test = fun(x: Int, y: Int): Int {
    
    
        return x + y
    }
    //通过test调用匿名函数
    println(test(2, 4))

    /*
    2. 函数作为参数传递, 可以用作回调: T.()->Unit 和 ()->Unit
       接受函数作为参数或者返回一个函数的函数就叫做高阶函数
     */

    //() -> Unit//表示无参数无返回值的Lambda表达式类型
    //(T) -> Unit//表示接收一个T类型参数,无返回值的Lambda表达式类型
    //(T) -> R//表示接收一个T类型参数,返回一个R类型值的Lambda表达式类型

    //()->Unit
    //2.1 不带参数和返回值的函数作为形参
    fun action0(method: () -> Unit) {
    
    
        method()
        println("this is action0")
    }

    fun method0() {
    
    
        println("this is method0 which is invoked")
    }

    action0 {
    
    
        println("this is action0")
    }

    fun action1(first: Int, method: () -> Unit) {
    
    
        method()
        println("this is action1")
    }

    //format->step1
    action1(1, {
    
    
        println("第1种写法")
    })
    //format->step2
    action1(1) {
    
    
        println("第2种写法")
    }

    val method: () -> Unit = {
    
    
        println("第3种写法")
    }
    action1(1, method)

    //2.2 带参数和返回值的函数作为形参
    fun method1(msg1: Int, msg2: Int): Int {
    
    
        println("this is method1")
        return msg1 + msg2;
    }

    fun getResult1(
        arg01: Int,
        arg02: Int,
        method: (arg1: Int, arg2: Int) -> Int
    ) {
    
    
        println("----->msg:before")
        val ret = method(arg01, arg02);
        println("----->msg:after = $ret")
    }

    println(getResult1(1, 2, ::method1))

    //T.()->Unit
    fun getResult3(
        method: Test.() -> Unit
    ) {
    
    
        println("----->msg:before")
        val test1 = Test()
        test1.apply(method)
        println("----->msg:after ${
      
      test1.a}")
    }

    println(
        getResult3(
            {
    
    
                a = "Tim"
            })
    )

    //2.3 函数作为参数, 指定加载位置和时机
    var host = false
    fun isHost() = host
    suspend fun getFromNet() {
    
    
        withContext(Dispatchers.IO) {
    
    
            delay(1000)
            host = true
        }
    }

    fun load(checkHost: () -> Boolean) {
    
    
        GlobalScope.launch() {
    
    
            getFromNet()
            if (checkHost.invoke()) println("yes, it's the host") else print("no, it's not the host")
        }
    }

    load {
    
     isHost() }

    /*
    3.1 类委托
     */
    val b = BaseImpl(10)
    Derived(b).print() // 输出 10
    Derived(b).otherPrint() //输出other

    /*
    3.2 属性委托
     */
    val isLogin: Boolean by DerivedProperty("tom")
    if (isLogin) {
    
    
        println("this is a property when invoked")
    }

    /*
    4. 协程
     */
    // 4.1 RxJava和协程的区别
    fun getUser(): Observable<String> {
    
    
        val random = Random()
        return Observable
            .create {
    
     emitter: ObservableEmitter<String> ->
                //模拟网络请求
                println("I'm doing network,CurrentThread is " + Thread.currentThread().name + "...")
                Thread.sleep(1000)
                if (random.nextBoolean()) {
    
    
                    emitter.onNext("Jack")
                } else {
    
    
                    emitter.onError(TimeoutException("Net Error!"))
                }
            }
            .subscribeOn(Schedulers.io())//指定网络请求在IO线程
    }

    fun rxjava() {
    
    
        getUser()
            .subscribe(object : Observer<String> {
    
    
                override fun onComplete() {
    
    
                }

                override fun onSubscribe(d: Disposable) {
    
    
                }

                override fun onNext(t: String) {
    
    
                    println(t)
                }

                override fun onError(e: Throwable) {
    
    
                }

            })
        Thread.sleep(2000)//延时2s,避免主线程销毁
    }
    //run
    rxjava()

    /* 4.2
     1. 可在全局创建协程: launch和runBlocking
     (1)launch是非阻塞的;
     (2)runBlocking是阻塞的;
     2. 可返回结果的协程: withContext和async
     (1)withContext与async都可以返回耗时任务的执行结果;
     (2)多个withContext任务是串行的, withContext可直接返回耗时任务的结果;
     (3)多个async任务是并行的, async返回的是一个Deferred<T>, 需要调用其await()方法获取结果;
     */
    //4.2.1.1: launch
    GlobalScope.launch {
    
    
        delay(1000)
        println("1.执行launch, [当前线程为:${
      
      Thread.currentThread().name}]")
    }
    println("2.Run launch, [当前线程为:${
      
      Thread.currentThread().name}]")
    //指定运行在主线程中
//    GlobalScope.launch(Dispatchers.Main) { println(Thread.currentThread().name) }

    //4.2.1.2: runBlocking
    runBlocking {
    
    
        delay(500)    //延时500ms
        println("1.执行runBlocking, [当前线程为:${
      
      Thread.currentThread().name}]")
    }
    println("2.Run runBlocking, [当前线程为:${
      
      Thread.currentThread().name}]")

    //4.2.2.1: withContext
    GlobalScope.launch {
    
    
        val time1 = System.currentTimeMillis()

        val task1 = withContext(Dispatchers.IO) {
    
    
            delay(2000)
            println("1.执行withContext-task1.... [当前线程为:${
      
      Thread.currentThread().name}]")
            "one"  //返回结果赋值给task1
        }

        val task2 = withContext(Dispatchers.IO) {
    
    
            delay(1000)
            println("2.执行withContext-task2.... [当前线程为:${
      
      Thread.currentThread().name}]")
            "two"  //返回结果赋值给task2
        }

        println("执行withContext-task1 = $task1  , 执行withContext-task2 = $task2 , 耗时 ${
      
      System.currentTimeMillis() - time1} ms  [当前线程为:${
      
      Thread.currentThread().name}]")
    }
    //4.2.2.1: async
    GlobalScope.launch {
    
    
        val time1 = System.currentTimeMillis()

        val task1 = async(Dispatchers.IO) {
    
    
            delay(2000)
            println("1.执行async-task1.... [当前线程为:${
      
      Thread.currentThread().name}]")
            "one"  //返回结果赋值给task1
        }

        val task2 = async(Dispatchers.IO) {
    
    
            delay(1000)
            println("2.执行async-task2.... [当前线程为:${
      
      Thread.currentThread().name}]")
            "two"  //返回结果赋值给task2
        }

        println("执行async-task1 = ${
      
      task1.await()}  , async-task2 = ${
      
      task2.await()} , 耗时 ${
      
      System.currentTimeMillis() - time1} ms  [当前线程为:${
      
      Thread.currentThread().name}]")
    }
    //4.2.3: 线程切换
    GlobalScope.launch(Dispatchers.Unconfined) {
    
    
        println("Dispatchers.Unconfined: ${
      
      Thread.currentThread().name}")//输出false

        //上下文切换到主线程
        GlobalScope.launch(Dispatchers.IO) {
    
    
            println("Dispatchers.IO: ${
      
      Thread.currentThread().name}}")//输出true
        }

    }
    //4.3 Scope: 协程作用范围
    //GlobalScope:表示此协程的生命周期随应用程序的生命周期, 没有和生命周期组件相关联
    //CoroutineScope:在应用中具有生命周期的组件应该实现CoroutineScope接口, 并负责该组件内 Coroutine 的创建和管理;
    //               以Activity为例, 比如标准库中定义的MainScope(), 另外参考KotlinInAndroid中的ScopedActivity和SimpleScopedActivity
    //viewModelScope(androidx.lifecycle.viewModelScope, androidx.lifecycle.lifecycleScope)

    /*
    5. 扩展函数
     */
    fun ExtClass.foo() = println("ext") // when the same as the member foo
    fun ExtClass.foo(para: Int) = println("ext")

    ExtClass().foo()
    ExtClass().foo(0)

    /*
    6. 闭包:函数中包含函数
     */
    val plus = {
    
     x: Int, y: Int -> println("$x plus $y is ${
      
      x + y}") }
    val hello = {
    
     println("Hello Kotlin") }
    fun closure(args: Array<String>) {
    
    
        {
    
     x: Int, y: Int ->
            println("$x plus $y is ${
      
      x + y}")
        }(2, 8)         // 自执行的闭包
        plus(2, 8)
        hello()
    }

    /*
    7. 单例
     */
    println("Singleton: " + Single.get().pro)

    /*
    8. Kotlin海量操作符, 替代RxJava操作符
     */
    fun rxjavaOperators() {
    
    
        //定义一个数组
        val index = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
//        Observable
//            .just(index)
//            .flatMap(object : Function<List<Int>, Observable<Int>> {
    
    
//                override fun apply(f: List<Int>): Observable<Int> {
    
    
//                    return Observable.fromIterable(f)
//                }
//            })
//            .filter(object : Predicate<Int> {
    
    
//                override fun test(p: Int): Boolean {
    
    
//                    return p % 2 == 0
//                }
//            })
//            .map(object : Function<Int, String> {
    
    
//                override fun apply(f: Int): String {
    
    
//                    return "[rxjava]String" + f
//                }
//            })
//            .subscribe(object : Consumer<String> {
    
    
//                override fun accept(t: String?) {
    
    
//                    println(t)
//                }
//            })
        Observable
            .just(index)
            .flatMap {
    
     Observable.fromIterable(it) }
            .filter {
    
     it % 2 == 0 }
            .map {
    
     "[rxjava]String$it" }
            .subscribe {
    
     println(it) }
    }
    rxjavaOperators()

    fun kotlinOperators() {
    
    
        val index = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
        index.filter {
    
     it % 2 == 0 }
            .map {
    
     "[kotlin]String$it" }
            .also {
    
     println(it) }
    }
    kotlinOperators()

    //将主线程延迟退出, 保证上面延时操作完成
    Thread.sleep(5000)
}

class ExtClass {
    
    
    fun foo() = println("origin")
}

class Test {
    
    
    var a: String? = null

}

// 创建接口
interface Base {
    
    
    fun print()
}

// 实现此接口的委托类
class BaseImpl(private val x: Int) : Base {
    
    
    override fun print() {
    
    
        println(x)
    }
}

// 通过关键字 by 建立代理类, 能够调用委托类已实现的方法和属性,不需再实现print()方法
class Derived(b: Base) : Base by b {
    
    
    fun otherPrint() {
    
    
        println("other")
    }
}

class DerivedProperty<T>(private val name: String) {
    
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
    
    
        println("this is a property delegate: $name")
        return when (name) {
    
    
            "tom" -> true as T
            "jerry" -> false as T
            else -> false as T
        }

        return true as T
    }

}

class Single private constructor() {
    
    
    val pro: Boolean = false

    companion object {
    
    
        fun get(): Single {
    
    
            return Holder.instance
        }
    }

    private object Holder {
    
    
        val instance = Single()
    }
}

4. Kotlin in Android

class KotlinInAndroid : AppCompatActivity() {
    
    

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //1. 控件直接用id, 不再使用findviewbyid
        btn_1.setOnClickListener(object : View.OnClickListener {
    
    
            override fun onClick(v: View?) {
    
    
                toastMe()
            }

        })
        btn_1.setOnClickListener {
    
     toastMe() } //lambda表达式更加简洁
        //2. 控件自定义方法
        iv_1.loadUrl("https://www.baidu.com/img/bd_logo1.png")
        //3. 扩展函数: 控件自定义方法可放在单独的类中
        toast("a toast")
        toast("a toast", Toast.LENGTH_LONG)
        //4. 协程
        //两个耗时操作,必须要在异步线程实现处理,处理完成后需要在主线程输出结果
        //way1:
        MainScope().launch {
    
    
            val startTime = System.currentTimeMillis()
            println("[way1]tag1:" + Thread.currentThread().name)
            val text1 = withContext(Dispatchers.IO) {
    
    
                println("[way1]tag2:" + Thread.currentThread().name)
                delay(1000)
                "Hello "
            }
            val text2 = withContext(Dispatchers.IO) {
    
    
                println("[way1]tag3:" + Thread.currentThread().name)
                delay(1000)
                "World!"
            }
            println("[way1]tag4:" + Thread.currentThread().name)
            println(text1 + text2)
            println("[way1]耗时:" + (System.currentTimeMillis() - startTime))
        }
        //way2:
        MainScope().launch {
    
    
            val startTime = System.currentTimeMillis()
            println("[way2]tag1:" + Thread.currentThread().name)
            val text1 = getHello("[way2]")
            val text2 = getWorld("[way2]")
            println("[way2]tag4:" + Thread.currentThread().name)
            println(text1 + text2)
            println("[way2]耗时:" + (System.currentTimeMillis() - startTime))
        }
        //way3:异步,不阻塞
        MainScope().launch {
    
    
            val startTime = System.currentTimeMillis()
            println("[way3]tag1:" + Thread.currentThread().name)
            val text1 = async {
    
     getHello("[way3]") }
            val text2 = async {
    
     getWorld("[way3]") }
            println("[way3]tag4:" + Thread.currentThread().name)
            println(text1.await() + text2.await())
            println("[way3]耗时:" + (System.currentTimeMillis() - startTime))
        }
        //way4:
        GlobalScope.launch(Dispatchers.Main) {
    
    
            var name = getResultFromNet()
            showResult(name)
        }
        //5. set赋值, text替换setText
        btn_1.text = "click me......"
        //6. scoped activity
        btn_2.setOnClickListener {
    
    
            startActivity(Intent(this, SimpleScopedActivity::class.java))
        }
    }

    private fun toastMe() {
    
    
        Toast.makeText(this, "clicked!", Toast.LENGTH_LONG).show()
    }

    fun ImageView.loadUrl(url: String) {
    
    //在任何类上添加函数
        Glide.with(iv_1.getContext()).load(url).into(iv_1)
    }

    private suspend fun getHello(way: String): String {
    
    
        return withContext(Dispatchers.IO) {
    
    
            println("$way tag2:" + Thread.currentThread().name)
            delay(1000)
            "Hello "
        }
    }

    private suspend fun getWorld(way: String): String {
    
    
        return withContext(Dispatchers.IO) {
    
    
            println("$way tag3:" + Thread.currentThread().name)
            delay(1000)
            "World!"
        }
    }

    private suspend fun getResultFromNet(): String {
    
    
        var name = ""
        withContext(Dispatchers.IO) {
    
    
            for (i in 0..1000000) {
    
    
                //这里模拟一个耗时操作
            }

            name = "ddnosh"
        }
        return name
    }

    private fun showResult(result: String) {
    
    
        println("[way4]=$result")
    }
}

欢迎关注我的技术公众号:国民程序员,我们的目标:输出干货

  1. 每天分享原创技术文章
  2. 海量免费技术资料和视频学习资源
  3. 分享赚钱门道,带领程序员走向财务自由
图片名称

猜你喜欢

转载自blog.csdn.net/ddnosh/article/details/115327206