Kotlin的基本使用

Kotlin的基本使用

  • 变量
    • val
    • var
  • 函数
  • 逻辑控制语句
    • if
    • when
    • for-in
  • 继承
  • 构造函数
    • 主构造函数
    • 次构造函数
  • 可见性修饰符
  • 数据类
  • 单例类
  • 集合
    • list集合
    • map集合
  • 空指针
  • 字符串中内嵌表达式

变量

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

val

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

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

val value = 10

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

val value : Int = 10

var

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

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

var value = 10
value = value - 5

函数

格式

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

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

 fun example(value: String) : Int{
 if (value != null){
            return value.length
        }
        return 0
    }

逻辑控制语句

if

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

   fun JudgeMax(paramA: Int , paramB: Int) : Int{
        var value = 0
         if (paramA > paramB)
            value = paramA
        else
            value = paramB
        return value
    }

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

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

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

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

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

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

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

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

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"
    }

示例二: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")
        }
    }

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")
        }
    }

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

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

示例三:当我们只需要一个数字内的偶数时,可使用关键字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")
        }
    }

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

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

继承

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

open class PersonUtil{
//do something ...
}

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

class StudentUtil : PersonUtil() {
    
}

构造函数

主构造函数

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

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

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

 init {
        //...
    }

次构造函数

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

    /**
     * 所有的次构造函数必须调用主构造函数*/
    constructor(name: String,age: Int,sex: String) : this(name,age) {
        //...
    }

    /**
     * 通过调用第一个次构造函数,间接调用主构造函数*/
    constructor() : this("",0,""){
   //...
    }

可见性修饰符

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

数据类

在类名前方加上data关键字

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

单例类

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

Kotlin的基本使用_第1张图片
/**
 * 单例类直接在创建的时候选择object,即在类名前方加上object*/
object SingleUtil {
    fun printName(name : String){
        Log.d("SingleUtil",name)
    }

    //外部调用SingleUtil.printName("")
}

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

集合

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

list集合

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

    /**
     * kotlin集合类与java类似*/
    fun listA(){
        val list = ArrayList()
        list.add("aaaa")
        list.add("bbbb")
        list.add("cccc")
    }

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

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

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

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

示例四:结合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() }
    }

示例五: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 }
    }

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){
            //...
        }
    }

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

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

可变

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

空指针

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

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

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

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

   /**
     * 此写法代表传入emotyB的参数允许为空*/
    fun emptyB(value: String?) {
        if (value != null) {
            //...
            value.lowercase()
        }

        /**
         * 可简化如下*/
        value?.lowercase()
    }

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

    /**
     * */
    fun emptyC(value: String?) : Int{
        if (value != null){
            return value.length
        }
        return 0
    }

    /**
     * 简化emptyC
     * ?:代表这左右两边都是一个表达式,若前者不为空则返回前者,否则返回后者
     * 与三目表达式类似*/
    fun emptyD(value: String?) = value?.length ?: 0

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

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

示例五:使用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()
        }
    }

字符串中内嵌表达式

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

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

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

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

你可能感兴趣的:(kotlin,kotlin,java,android)