• Kotlin的基本使用


    变量

    由于kotlin优秀的类型推导机制,在定义变量时无需声明其类型,只需根据场景使用var和val进行定义即可

    val

    类似于java中加了final的修饰的变量,其值初始化后不可改变

    如下定义了一个不可变的整形变量

    val value = 10
    
    • 1

    便于代码可读性,我们可以显式声明其类型

    val value : Int = 10
    
    • 1

    var

    类似于java中非final修饰的变量

    如下定义了一个可变的整形变量

    var value = 10
    value = value - 5
    
    • 1
    • 2

    函数

    格式

    fun 函数名称(参数1:参数类型,参数2:参数类型):返回类型{}
    
    • 1

    以下为计算某个字符串的长度,fun为kotlin内定义函数的关键字;若不需要返回值,直接省略
    :返回类型即可,则对应java中void关键字修饰的方法

     fun example(value: String) : Int{
     if (value != null){
                return value.length
            }
            return 0
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    逻辑控制语句

    if

    以比较两数大小作为例子,具体如下所示:
    示例一:传入两个整形参数,返回类型为Int,通过if进行比较,返回较大值

       fun JudgeMax(paramA: Int , paramB: Int) : Int{
            var value = 0
             if (paramA > paramB)
                value = paramA
            else
                value = paramB
            return value
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例二:因为在kotlin中if是带返回值的,所以根据示例一,可简写为如下;当只有一句表达式时,可省略{}

     /**
         * fun:方法/函数定义关键字
         * JudgeMaxA:方法/函数名称
         * 括号内:若需要形参,则:参数名称:参数类型;多个参数中间用逗号隔开,若不需要参数,空括号即可
         * 返回类型:Int*/
     fun JudgeMaxA(paramA: Int , paramB: Int) : Int{
            val value = if (paramA > paramB)
                paramA
            else
                paramB
            return value
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    示例三:根据示例二继续简写,直接通过比较返回,无需额外建立一个局部变量

    /**
         * 因为在kotlin中if具有返回值的功能,所以可简写为如下*/
        fun JudgeMaxB(paramA: Int , paramB: Int) : Int{
            return if (paramA > paramB)
                paramA
            else
                paramB
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例四:当函数只有一行代码时,无需编写函数体,直接使用=号连接函数即可,在由于kotlin自动类型推导功能,直接在函数之后进行if判断

     /**
         * 由于if具有返回值功能,加上kotlin自动类型推导功能,可以使用=号进行连接,并且因为传入型参为int型,所以函数返回类型也可省略*/
        fun JudgeMaxC(paramA: Int , paramB: Int) = if (paramA > paramB)
            paramA
        else
            paramB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例五:使用内置函数max,其返回值为int型,故与C例同理

     /**
         * 使用内置函数max,其返回值为int型,故与C例同理*/
        fun JudgeMaxD(paramA : Int , paramB : Int) = max(paramA,paramB)
    
    • 1
    • 2
    • 3

    when

    kotlin中的whenjava中的switch类似,但switch只支持整形、短整形,在1.8之后支持字符串匹配,但when支持任何类型匹配

    示例一:when同样带返回值,当执行逻辑只有一个表达式时,可省略{}函数体;其中else等同于java中的default关键字,当前面没有匹配项时,执行else

      /**
         * when函数类似于java中的switch函数
         * when函数允许传入任意类型参数
         * 其中else对应switch的default
         * 格式:匹配值 -> {执行逻辑}
         * 当执行逻辑只有一句话时,包裹的{}可省略*/
        fun getName(id : String) = when (id){
            "111" -> {"Tom"}
            "222" -> "Jack"
            "333" -> "Peter"
            else -> "NULL"
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    示例二:Number是一个内置的抽象类,Int,Double,Long…都是其子类
    is为内置关键字,类似于java中的instance;通过判断传入参数类型,打印相对于的类型

       /**
         * Number是一个内置的抽象类,Int,Double,Long...都是其子类
         * is为内置关键字,类似于java中的instance*/
        fun getType(num : Number){
            when(num){
                is Int -> Log.d("type","type = Int")
                is Double -> Log.d("type","type = Double")
                else -> Log.d("type","type = null")
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    for-in

    kotlin中舍弃了for-i,引进了for-in,类似于加强版for-each
    示例一:区间为kotlin的特点之一,..为双端区间写法

       /**
         * .. 双端区间,等同于数学中的闭区间[0,10]
         * 区间左端必须小于等于右边
         * for-in为java中for-each加强版
         * 因为kotlin的类型推导机制,循环变量i不需要定义类型*/
        fun testForInA(){
            val range = 0 .. 10
            for ( i in range){
                Log.d(TAG, "current num = $i")
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    示例二:因为数组下标是从0开始,所以在遍历数组时,数组长度为n的数组,当下标移动到n即越界,所以使用until关键字,代表左开右闭区间

     /**
         * until 左开右闭区间,等同于数学中的闭区间[0,10)
         * 区间左端必须小于等于右边
         * for-in为java中for-each加强版
         * 因为kotlin的类型推导机制,循环变量i不需要定义类型*/
        fun testForInB(){
            val range = 0 until 10
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例三:当我们只需要一个数字内的偶数时,可使用关键字step,控制下标移动步长

     /**
         * step : 等同于i+=2*/
        fun testForInC(){
            val range = 0 until 10
            // val range = 0 until 10 step 2
            for (i in range step 2){
                Log.d(TAG, "current num = $i")
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例四:以上..until两种区间关键字都是代表着升序,即左边值必须小于等于右边的值,当我们需要体现降序时,可使用关键字downTo

     /**
         * ..和until都是左边小于等于右边,即为升序
         * 若需使用降序,则使用downTo关键字,数学表达式为:[10,0]*/
        fun testForInD(){
            val range = 10 downTo 0
            for (i in range){
                Log.d(TAG, "current num = $i")
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    继承

    kotlin中非抽象类不可被继承,如需此类允许被外界子类继承,则需在类名前方加上open关键字,代表此类允许被继承
    示例:

    open class PersonUtil{
    //do something ...
    }
    
    • 1
    • 2
    • 3

    子类继承如下,使用:代替java中的extends关键字,即实现接口也使用:,代替implements

    class StudentUtil : PersonUtil() {
        
    }
    
    • 1
    • 2
    • 3

    构造函数

    主构造函数

    在kotlin中有主构造函数次构造函数之分,只允许有一个主构造函数,可以拥有多个此构造函数,两者区别在于,主构造函数没有函数体,直接在类名之后完成定义

    open class PersonUtil(name: String , age: Int) {
    }
    
    • 1
    • 2

    若如需在主构造函数内执行一些逻辑,可在init函数内完成

     init {
            //...
        }
    
    • 1
    • 2
    • 3

    次构造函数

    次构造函数使用constructor关键字声明,其中次构造函数必须调用主构造函数

        /**
         * 所有的次构造函数必须调用主构造函数*/
        constructor(name: String,age: Int,sex: String) : this(name,age) {
            //...
        }
    
        /**
         * 通过调用第一个次构造函数,间接调用主构造函数*/
        constructor() : this("",0,""){
       //...
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    可见性修饰符

    修饰符JavaKotlin
    public所有类可见所有类可见(默认)
    private当前类可见当前类可见
    protected当前类、子类、同包路径下可见当前类、子类可见
    default同包路径下可见(默认)
    internal同一模块中的类可见

    数据类

    在类名前方加上data关键字

    /**
     * data:即为数据类,系统自动重新toString(),hashCode(),equal()等方法,减少不必要代码量*/
    data class BeanUtil(val value : String)
    
    • 1
    • 2
    • 3

    单例类

    在java中需要私有化构造方法,防止外部new新对象,还需要synchronized和双重判空去优化单例获取,但在kotlin中只需要在创建的时候选择object即可自动生成

    /**
     * 单例类直接在创建的时候选择object,即在类名前方加上object*/
    object SingleUtil {
        fun printName(name : String){
            Log.d("SingleUtil",name)
        }
    
        //外部调用SingleUtil.printName("")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    外部引用 SingleUtil.printName("test")

    集合

    kotlin中的集合与java中的无异,只是在使用方法上做出很大简便

    list集合

    示例一:添加与删除都有java一样

        /**
         * kotlin集合类与java类似*/
        fun listA(){
            val list = ArrayList()
            list.add("aaaa")
            list.add("bbbb")
            list.add("cccc")
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例二:listOf关键字声明的集合具有不可变性,即不能进行删除和添加等修改操作,但同样完成简化,无需使用add方法进行元素添加

      /**
         * listOf可简化初始化过程,但为不可变性,即为不能对集合进行添加、删除等操作*/
        fun listB(){
            val list = listOf("aaaa","bbbb","cccc")
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    示例三: mutableListOflistOf基础上允许对集合进行添加、删除等操作

      /**
         * mutableListOf在listOf基础上允许对集合进行添加、删除等操作*/
        fun listC(){
            val list = mutableListOf("aaaa","bbbb")
            list.add("cccc")
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例四:结合lambda,可以进一步简化代码

    /**
         * 利用lambda集合式API寻找集合内长度最大的子项*/
        fun mapB(){
            val list = listOf("aaaa","bbbbb","cccccc")
            val lambda = {value : String -> value.length}
            val maxLengthA = list.maxOf(lambda)
    
            /**
             * 不需要专门定义一个lambda变量,可直接放入函数中*/
            val maxLengthB = list.maxOf { value: String -> value.length }
    
            /**
             * 由于类型推导机制的存在,可省略变量的类型*/
            val maxLengthC = list.maxOf { value -> value.length }
    
            /**
             * 当lambda参数列表只剩一个参数时,可用关键字it代替*/
            val maxLengthD = list.maxOf { it.length }
    
            /**
             * map函数即映射为一个新的元素,最终形成一个新的list集合*/
            val upMap = list.map { it.uppercase() }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    示例五:filter:用于过滤集合中的某些子项,参数类型为boolean

      /**
         * filter:用于过滤集合中的某些子项,参数类型为boolean*/
        fun mapC(){
            val list = listOf("aaaa","bbbbb","cccccc")
            val newList = list.filter { it.length <= 2 }
                .map { it.uppercase() }
    
            /**
             * any:用于判断集合类是否至少存在一个满足条件的元素
             * 返回类型:boolean*/
            val any = list.any { it.length <= 5 }
    
            /**
             * all:用于判断集合类是否全部的元素都满足条件
             * 返回类型:boolean*/
            val all = list.all { it.length <= 5 }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    map集合

    示例一: map除了使用标准的put和get方法还可使用类似数组的存储、读取方式

     /**
         * map除了使用标准的put和get方法还可使用类似数组的存储方式
         *如下所示 */
        fun mapA(){
            val map = HashMap()
            map.put("aaaa",1)
            var numA = map.get("aaaa")
    
            map["bbbb"] = 2
            var numB = map["bbbb"]
    
            for((value,num) in map){
                //...
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    示例二:同样map集合也可声明可变和不可变类型,其中使用to关键字来对键值对进行关联
    不可变

     val mapOf = mapOf("aaaa" to 1,"bbbb" to 2)
    
    • 1

    可变

     val mapMult = mutableMapOf("aaaa" to 1,"bbbb" to 2)
    
    • 1

    空指针

    空指针异常在各种编程语言中都是出现频率较高的异常之一,kotlin通过空指针检查优化此缺陷

    示例一:此写法代表传入emptyA的参数不能为空,若在外部传入空,系统会给予异常提示,无法通过编译
    在这里插入图片描述

      /**
         * 此写法代表传入emptyA的参数不能为空*/
        fun emptyA(value : String){
            Log.d("empty","value$value")
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    示例二:在参数类型后加上?,即代表此参数允许为空;在变量后加上?.即代表若不为空则执行后续表达式,否则不执行

       /**
         * 此写法代表传入emotyB的参数允许为空*/
        fun emptyB(value: String?) {
            if (value != null) {
                //...
                value.lowercase()
            }
    
            /**
             * 可简化如下*/
            value?.lowercase()
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    示例三:?:代表这左右两边都是一个表达式,若前者不为空则返回前者,否则返回后者

        /**
         * */
        fun emptyC(value: String?) : Int{
            if (value != null){
                return value.length
            }
            return 0
        }
    
        /**
         * 简化emptyC
         * ?:代表这左右两边都是一个表达式,若前者不为空则返回前者,否则返回后者
         * 与三目表达式类似*/
        fun emptyD(value: String?) = value?.length ?: 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    示例四:定义一个可为空的全局变量,在emptyE中对其判空处理,在不为空的情况下执行emptyF, 在emptyF中将全局变量转为大写,但此时不能完成编译,因为uppercase方法不知道外部进行类判空处理,所以需要加上非空断言工具!!,即非常确定此处不为

     /**
         * 定义一个可为空的全局变量,在emptyE中对其判空处理,在不为空的情况下执行emptyF
         * 在emptyF中将全局变量转为大写,但此时不能完成编译
         * 因为uppercase方法不知道外部进行类判空处理,所以需要加上非空断言工具!!,即非常确定此处不为空,强制编译*/
        var sampleA : String? = "hello"
        fun emptyE(){
            if (sampleA != null){
                emptyF()
            }
        }
        fun emptyF(){
            sampleA!!.uppercase()
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    示例五:使用let函数调用lambda表达式,不仅可以简化代码,还可以减少代码执行时间复杂度

     /**
         * 使用if语句进行判空处理,只需执行一次
         * 当使用?.时,每调用一次便需要进行一次判空处理*/
        fun emptyG(iSample: ISample?){
            if (iSample != null){
                iSample.doWork()
                iSample.doSleep()
            }
    
            iSample?.doWork()
            iSample?.doSleep()
        }
    
        /**
         * 简化emptyG函数,使用let函数调用lambda表达式*/
        fun emptyH(iSample: ISample?){
            iSample?.let { stu->
                stu.doWork()
                stu.doSleep()
            }
    
            iSample?.let {
                it.doWork()
                it.doSleep()
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    字符串中内嵌表达式

    在java中需要使用+去拼接字符串,也可以使用StringBuilder,但是在字符串内嵌表达式目前java还不支持,可以在string.xml中定义字符串,并需要动态修改的地方加上%1$s%1$d占位符,然后在java代码中找到此资源,然后format,才能进行内嵌,过程实属麻烦。在kotlin中支持字符串内嵌表达式
    示例一:使用$进行声明,使用{}进行包裹

      fun emptyA(value : String){
            Log.d("empty","value${value}")
        }
    
    • 1
    • 2
    • 3

    示例二:当只有一个参数时,可省略{}

     fun emptyA(value : String){
            Log.d("empty","value$value")
        }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    自学黑客(网络安全)
    一种用于Linux内核驱动开发的Vim环境配置
    存储架构颠覆者Optane持久性内存
    span标签的作用
    flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单AdaptiveTextSelectionToolba样式UI效果
    参加2024年CSDN博客_付费内容优质创作者_颁奖仪式的收获
    【构建并发程序】3-原子变量
    vue-element-admin—登录页面添加自定义背景
    前端面试要点
    【TB作品】MSP430,G2533单片机,红外发射,红外接收,红外通信,IR发射
  • 原文地址:https://blog.csdn.net/News53231323/article/details/126581682