kotlin 练习1

package com.zsw.myandroidlearnapplication.kotlin

import java.io.File
import kotlin.math.roundToInt

/**
 *@author zengsuwa
 *@date 2023/4/19
 *@desc
 *
 */
//TODO 内置函数的总结
// let 函数返回类型是根据匿名函数最后一行的变化而变化,
// let函数的匿名函数持有的是it == 集合本身
// apply
// apply函数返回值,一直都是info本身
// apply函数里面持有的是this == info本身

/**  todo Kotlin内置函数总结
 *   1.apply info.apply
 *   apply 函数返回类型用于都是info本身
 *   apply 函数的匿名函数里面持有的是this == info本身
 *
 *   2.let str.let
 *   let 函数的返回类型是根据 匿名函数的最后一行变化而变化
 *   let 函数的匿名函数里面持有的是it == 集合本身

 *   3.run str.run
 *   run 函数的返回类型是根据 匿名函数的最后一行变化而变化 这一点跟let一样
 *   run 函数的匿名函数里面持有的是this == str本身(谁点出来的就持有谁) 这一点跟apply一样

 *   4.with  with(str) with 和run基本上一样,就是使用方法上不一样
 *   with 函数的返回类型是根据 匿名函数的最后一行变化而变化 这一点跟let一样
 *   with 函数的匿名函数里面持有的是this == str本身(谁点出来的就持有谁) 这一点跟apply一样
 *
 *   5.also str.also
 *   函数返回类型用于都是str本身 这一点跟apply一样
 *   函数的匿名函数里面持有的是it == str本身 这一点跟let一样
 *
 *   6.takeIf
 *   如果takeIf里面返回的是false 那么这个表达式返回的是null ,如果takeIf里面返回的是true,那么这个表达式返回的是name本身
 *   name.takeIf {true/false}
 *   函数的匿名函数里面持有的是it == name本身 这一点跟let一样
 *
 *   7.takeUnless
 *   如果takeUnless里面返回的是false 那么这个表达式返回的是name本身 ,如果takeUnless里面返回的是true,那么这个表达式返回的是null
 *   takeIf和takeUnless的功能是相反的
 *   name.takeUnless {true/false}
 *
 */
class Base01 {


}

private fun add(number: Int, number2: Int): Int {

    return number + number2
}

//TODO 匿名函数 == lambda表达式
var methodAction = { num1: Int, num2: Int, result: String ->
    var sum = num1 + num2
    result + sum
}

//返回Any类型 类似于Java中的Object
val methodAction2 = { num: Int ->
    when (num) {
        1 -> "星期一"
        2 -> "星期二"
        3 -> "星期三"
        4 -> "星期四"
        5 -> "星期五"
        6 -> "星期六"
        7 -> "星期日"
        else -> -1
    }

}


//在Java中写法
//    public void login(String username,String pwd,CallBack callback){
//      String result = httpRequest(username,pwd);
//      callback(result)
//    }
//resultCallback 可以等同于Java接口回调的作用
//在函数中定义的参数是函数的函数

fun login(username: String, pwd: String, resultCallback: (result: String, Int) -> Unit) {
    if (username == null || pwd == null) {
        TODO("用户名或密码为空,程序不会往下执行")
    }
    if (webService(username, pwd)) {
        resultCallback("登录成功", 200)
    } else {
        resultCallback("登录失败", 400)
    }
}
//这个函数里面有使用lambda表达式作为参数所以需要声明成内联函数
// 如果此函数不使用内联,在调用端会生成多个对象来完成对lambda的调用(会造成性能损耗)
// Tools->Kotlin ->show Kotlin Bytecode ->Decompile查看字节码可看到转成了Function2对象
//      login2("xiaoming", "123456", (Function2)null.INSTANCE);
// 如果此函数使用内联,相当于C++ #define 宏定义 宏替换 会把代码替换到调用处,调用处没有任何函数开辟 对象开辟的损耗
//小结:如果函数有lambda 尽量使用inline关键字 内联 这样内部会做优化减少函数开辟,对象开辟的损耗
//main()函数里面字节码转换login2的调用处变成如下代码
//
//String username$iv = "xiaoming";
//String pwd$iv = "123456";
//int $i$f$login2 = false;
//short code;
//String result;
//boolean var5;
//String var6;
//if (webService(username$iv, pwd$iv)) {
//    code = 200;
//    result = "登录成功";
//    var5 = false;
//    var6 = result + ",状态码" + code;
//    System.out.println(var6);
//} else {
//    code = 400;
//    result = "登录失败";
//    var5 = false;
//    var6 = result + ",状态码" + code;
//    System.out.println(var6);
//}

inline fun login2(username: String, pwd: String, resultCallback: (result: String, Int) -> Unit) {
    if (username == null || pwd == null) {
        TODO("用户名或密码为空,程序不会往下执行")
    }
    if (webService(username, pwd)) {
        resultCallback("登录成功", 200)
    } else {
        resultCallback("登录失败", 400)
    }
}

//这个函数里面没有使用lambda表达式作为参数所以不需要声明成内联函数
fun webService(username: String, pwd: String): Boolean {
    return username == "xiaoming" && pwd == "123456"
}

fun resultMethod(msg: String, code: Int) {
    println("$msg,状态码$code")
}

//返回一个函数
fun returnMethod(info: String): (String, Int) -> String {
    println("info=$info")
    return { name: String, age: Int ->
        val ageStr = when (age) {
            in 1..18 ->
                "小孩"
            in 20..60 ->
                "成年人"
            else ->
                "老人"
        }
        "name=$name,age=${age}是个$ageStr"
    }
}

//入参为函数
inline fun method1(name: String, age: Int, sex: Char, canshuMethod: (info: String) -> Unit) {
    val info1 = "name:$name,age:$age,sex:$sex"
    canshuMethod(info1)
}

fun method2(info: String) {
    println("hahah*********info:$info")
}

fun checkException(info: String?) {
    info ?: throw CustomException() //忘记加 throw 就不会抛出
}

class CustomException : java.lang.IllegalArgumentException("你的代码不严谨")

fun isLong(str: String) = str.length > 5
fun showText(isLong: Boolean) = if (isLong) "你的字符串合格" else "你的字符串不合格"
fun mapText(str: String) = "[$str]"

fun checkPermissionAction(name: String, pwd: String): String? {
    //如果takeif里面返回的是false 那么这个表达式返回的是null ,如果takeIf里面返回的是true,那么这个表达式返回的是name本身
    //name.takeIf {true/false}
    return name.takeIf {
        checkPermission(it, pwd)
    }
}

//一般大部分情况下takeIf都跟空合并操作符一起使用
fun checkPermissionAction2(name: String, pwd: String): String {
    //如果takeif里面返回的是false 那么这个表达式返回的是null ,如果takeIf里面返回的是true,那么这个表达式返回的是name本身
    //name.takeIf {true/false}
    return name.takeIf {
        checkPermission(it, pwd)
    } ?: "您的权限不够"
}

private fun checkPermission(name: String, pwd: String): Boolean {
    return (name == "root" && pwd == "123456")
}

class Manager {
    private var infoValue: String? = null

    fun getInfoValue() = infoValue
}

fun main() {
    //会提示不能是非空类型的String值
    var name = "hahah"
//    name = null
    //声明指定为可空类型
    var name2: String? = "xiaoming"
    name2 = null
    //?: 空合并操作符
    val info = name2 ?: "这个值为空"

    println(info)//打印 这个值为空
    //capitalize() 首字母大写的作用
    //补救措施
    //1.?
    name2?.capitalize()//name2 为可空类型,?.空安全运算符 表示如果name2为空,那么后面那一节不执行

    //2. !!
    try {
//        checkException(name2)//com.zsw.myandroidlearnapplication.kotlin.CustomException: 你的代码不严谨
        //TODO 可以使用checkNotNull() requireNotNull 检查是否value为空,为空则抛出异常
        // require检查是否value为false 为false则抛出异常
//        checkNotNull(name2)//检查value是否不为空, java.lang.IllegalStateException: Required value was null
//        requireNotNull(name2)//检查value是否不为空 java.lang.IllegalArgumentException: Required value was null.

        val value = false
        require(value)//如果值为false则抛出异常 java.lang.IllegalArgumentException: Failed requirement.
        println(name2!!.capitalize()) //!! 非空断言运算符 表示name2必不为空, 如果为空就会引发空指针
    } catch (e: Exception) {
//        e.printStackTrace()
        println(e)
        println("哎呀${e.message}")
    }

    val info3 = "hello world!"
    val indexOf = info3.indexOf("w")
    //均输出 hello
    //hello+空格
    println(info3.substring(0, indexOf))//这两种写法是等价的
    println(info3.substring(0 until indexOf))//KT 中一般都使用这种方式

    //3。if
    if (name2 != null) {
        name2.capitalize()
    } else {
        println("name2 is null")
    }
    //TODO 在kt中使用带let的安全调用
    //?后面不执行,不会引发空指针
    val r = name2?.let {
        //能执行到这里说明 name2肯定不为空 isBlank 是"" 没有内容
        if (name2.isBlank()) {
            "Default"
        } else {
            "[$it]"
        }
    }

    println(r)


    //{ result, code ->
    //        println("$result,状态码$code")
    //    }
    //这一部分是Login函数中定义的函数的实现
    //lambda表达式 可以写在括号里面也可以写在括号外面
    //第一种方式
    login("xiaoming", "123456", resultCallback = { result: String, code: Int ->
        println("$result,状态码$code")
    })
    //第二种方式
    login2("xiaoming", "123456", { result: String, code: Int ->
        println("$result,状态码$code")
    })
    //第三种方式 最优
    login("xiaoming", "123456") { result, code ->
        println("$result,状态码$code")
    }

    //TODO 第四种方式 函数引用 ::
    // lambda属于函数类型的对象 ,需要把resultMethod普通函数转变成 函数类型的对象(函数引用)在使用函数的前面加上::
    // 传递了一个函数进来 resultMethod
    login2("xiaoming", "123456", ::resultMethod)
    //定义了 obj 这个变量来接收函数类型的对象
    val obj = ::resultMethod
    val obje = obj
    login2("xiaoming", "123456", obje)

    println("4 + 5 = ${add(4, 5)}")
    println(methodAction(2, 5, "两数之和为"))
    //放开TODO的注释 会抛出这个异常
    // Exception in thread "main" kotlin.NotImplementedError:
    // An operation is not implemented: 出现问题,程序不会往下执行
//    TODO("出现问题,程序不会往下执行")
    println(methodAction2(6))

    val nimingMethod = returnMethod("xiaoming")//立即打印结果 info=xiaoming
    println(nimingMethod("zhangsan", 12))//调用这一行才会打印

    //入参为匿名函数
    method1("zhangsan", 14, '男') {
        println(it)
    }
    //入参为具名函数 需要使用:: 把普通函数转换为 函数类型的对象
    method1("wangwu", 20, '男', ::method2)

    val jsonText = "zhangsan,lisi,wangwu,zhaoliu"
    //根据","截取成List<String>集合
    val list = jsonText.split(",")
    //直接输出list 不解构
    println("分割后的list里面的元素有:$list")
    //c++ 解构 KT也有解构

    //这里面如果加一个v5会报错 Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
    val (v1, v2, v3, v4) = list

    //解构后的四个只读变量为:v1:zhangsan,v2:lisi,v3:wangwu,v4:zhaoliu
    println("解构后的四个只读变量为:v1:$v1,v2:$v2,v3:$v3,v4:$v4")

    //45.TODO kotlin replace 完成加密解密操作

    val password = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    println("原密码:$password")

    //加密操作就是把字符串替换成数字 打乱了 就属于加密了
    val jiamipwd = password.replace(Regex("[AKMNO]")) {
//        it.value//如果这里是返回这个,表示什么事情都没做,没加密 it.value 是取出password中通过正则表达式的每个字符,然后返回有点类似与遍历当前字符串的字符
        print("${it.value}   ")//打印的是: A   K   M   N   O

        when (it.value) {
            "A" -> "9"
            "K" -> "3"
            "M" -> "1"
            "N" -> "5"
            "O" -> "4"
            else ->
                it.value
        }
    }
    println()

    println("加密后的密码:$jiamipwd")

    val jiemiPwd = jiamipwd.replace(Regex("[93154]")) {
        when (it.value) {
            "9" -> "A"
            "3" -> "K"
            "1" -> "M"
            "5" -> "N"
            "4" -> "O"
            else -> it.value
        }
    }

    println("解密后的密码:$jiemiPwd")

    //== 值内容的比较 相当于Java的equals
    //=== 引用的比较

    val name3 = "Derry"
    val name4 = "Derry"
    println(name3 == name4) //true
    println(name3 === name4) //true  其实指向的都是同一个字符串常量池中的这个常量
    val name6 = "jerry"
    println(name3 == name6)
    println(name3 === name6)

    val name5 = "derry".capitalize()
    println(name5)//Derry

    println(name3 === name5)//false

    password.forEach {
        print("$it ")
    }
    println()

    val num1 = "888".toInt()
//    val num2 = "888.8".toInt()//会抛异常  Exception in thread "main" java.lang.NumberFormatException: For input string: "888.8"
    val num3: Int? = "888.8".toIntOrNull()//不会抛异常 值为null
    //TODO 以后字符串转Int尽量都使用toIntOrNull此函数

    println(65.469778.toInt())//65
    println(65.4692873.roundToInt())//65
    println(65.579890.roundToInt())//66
    //roundToInt Double转Int四舍五入

    //r 的类型字符串类型 保留小数点后三位数 也会四舍五入
    val rel = "%.3f".format(65.4697873)
    val rel2 = "%.3f".format(65.4692873)
    println(rel)//65.470
    println(rel2)//65.470


    val info2 = "nihao XiaoMing"

    println("info长度${info2.length}")
    println("info最后一个字符是${info2[info2.length - 1]}")
    println("info的全部转成小写是${info2.lowercase()}")
    //info2.apply 始终返回info2 本身
    val info4 = info2.apply {
        //大部分情况下,匿名函数都会持有一个it,但是apply()函数不会持有it,却会持有当前this == info2 本身
        println("info长度${length}")
        println("info最后一个字符是${this[length - 1]}")
        println("info的全部转成小写是${lowercase()}")
    }
    println(info4)

    info2.apply {
        println("info长度${length}")
    }.apply {
        println("info最后一个字符是${this[length - 1]}")
    }.apply {
        println("info的全部转成小写是${lowercase()}")
    }

    val file = File("/Users/sunnyzeng/Desktop/a.txt")
    //普通方式
    file.setExecutable(true)
    file.setReadable(true)
    println(file.readLines())

    //apply方式
    val file2: File = file.apply {
        setExecutable(true)
        setReadable(true)
        println(readLines())
        true
    }


    val sum = listOf(6, 5, 4, 3, 2, 1).let {
        println(it)//[6, 5, 4, 3, 2, 1]
        it.first() + it.first()//匿名函数的最后一行作为返回值,let的特点,但是前面学的apply永远返回info本身
    }
    println(sum)

    var name8: String? = "null"
    name8 = null
    name8?.let {

    }

    val str3 = "derry is ok"

    //这个属于匿名函数配合run
    str3.run {
//        this == str3
    }
//    这个是属于具名函数配合run
//    str3.run(具名函数)
    println("******* run ********")
    str3.run(::isLong) //this 为String ; return Boolean
        .run(::showText)// this 为Boolean ; return String
        .run(::mapText)//this 为String ; return String
        .run(::println)//this 为 String ;return Uint

    println("******* let ********")
    str3.let(::isLong) //it 为String ; return Boolean
        .let(::showText)// it 为Boolean ; return String
        .let(::mapText)//it 为String ; return String
        .let(::println)//it 为 String ;return Uint

    println("******* with ********")
    val r1 = with(str3, ::isLong)
    val r2 = with(r1, ::showText)
    val r3 = with(r2, ::mapText)
    with(r3, ::println)


    //以上是具名函数配合run,以下是匿名函数配合run
    str3.run { length > 5 }
        .run { if (this) "run 你的字符串合格" else "你的字符串不合格" }
        .run { "[$this]" }
        .run { println(this) }

    str3.let { it.length > 5 }
        .let { if (it) "let 你的字符串合格" else "你的字符串不合格" }
        .let { "[$it]" }
        .let { println(it) }

    with(with(with(with(str3) {
        length > 5
    })
    {
        if (this) "with 你的字符串合格" else "你的字符串不合格"
    }) {
        "[$this]"
    }) {
        println(this)
    }

    val result: String = str3.also {
        123
    }

    //also 匿名函数永远返回的都是他自己
    password.also {
        println("password的源数据是$it")
    }.also {
        println("password转换成小写的效果是${it.lowercase()}")
    }.also { println(it) }

    val re1 = checkPermissionAction("root", "123456")
    if (rel != null) {
        println("欢迎${re1}尊贵的用户登录超级系统,拥有超级权限")
    } else {
        println("您的权限不够")
    }

    println(checkPermissionAction2("root1", "123456"))

    val manager = Manager()
    //takeUnless+ it.isNullOrBlank 一起使用可以验证字符串有没有初始化等功能
    val take11 = manager.getInfoValue().takeUnless { it.isNullOrBlank() } ?: "没有任何的初始化操作"
    val take22 = manager.getInfoValue().takeIf { !it.isNullOrBlank() } ?: "没有任何的初始化操作"
    println(take11)
    println(take22)
}


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