【Android】Kotlin教程(1)

文章目录

1.声明变量

可变变量定义:var 关键字

kotlin 复制代码
var a:Int = 1

不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)

kotlin 复制代码
val a:Int = 1

2.类型推断

类型推断:对于已声明赋值的变量,它允许省略类型定义。

3.range表达式

in A...B 关键字用来检查某个值是否在指定范围之内。

kotlin 复制代码
	if(age in 0..18){
        println("少年")
    }else if(age in 18..40){
        println("成年")
    }

4.when表达式

  • 允许你编写条件式,在某个条件满足时,执行对应代码
  • 只要包含else if分支,都建议改用when表达式
kotlin 复制代码
    val school = "小学"
    val level = when(school){
        "小学" -> 1
        "初中" -> 2
        "高中" -> 3
        else -> 0
    }
    println("level: " + level);

5.string模版

  • 模版支持在字符串的引号内放入变量值。
  • 还支持字符串里计算表达式的值并插入结果,添加在${}中的任何表达式,都会作为字符串的一部分求值。
kotlin 复制代码
    val school = "小学"
    println("$school")
    
    val flag = false
    println("Answer is : ${if(flag) "Yes" else "No"}")

6.函数

函数定义使用关键字 fun,参数格式为:参数 : 类型

kotlin 复制代码
fun add(a:Int , b:Int):Int{
    return a+b;
}

无返回值的函数

kotlin 复制代码
fun addNoReturn1(a:Int,b:Int,c:Int = 1){
    println("结果" + (a+b+c))
}

fun addNoReturn2(a:Int,b:Int,c:Int = 1) :Unit{
    println("结果" + (a+b+c))
}

可变长参数函数

kotlin 复制代码
fun addToSum(vararg nums:Int):Int{
    var sum = 0
    for(num in nums){
        sum += num
    }
    return sum
}

7.数据类型

Java中有两种数据类型:引用类型和基本数据类型。

Kotlin只提供引用类型这一种数据类型,出于更高性能的需要,Kotlin编译器会在Java中改用基本数据类型。

Kotlin 提供了多种内置数据类型,这些类型大致可以分为以下几类:
整数类型

  • Byte:8位有符号整数
  • Short:16位有符号整数
  • Int:32位有符号整数
  • Long:64位有符号整数

浮点类型:

  • Float:32位单精度浮点数
  • Double:64位双精度浮点数

字符类型

  • Char:表示一个单一的 16 位 Unicode 字符

布尔类型

  • Boolean:表示逻辑上的真(true)或假(false)

数组类型

  • 数组是一种用于存储固定大小的同类型元素的集合。例如,IntArray 用来存放整数数组,Array 用来存放字符串数组等。

字符串类型

  • String:不可变的字符序列

除了上述的基本类型外,Kotlin 还提供了一些特殊的类型如 Unit 和 Nothing:

  • Unit 类型类似于 Java 中的 void,它代表没有任何信息的值。如果一个函数没有返回任何有意义的结果,那么它的返回类型就是 Unit。
  • Nothing 类型则代表一个永远不会返回结果的函数。这种类型的函数通常用于抛出异常或者无限循环中。
    另外,Kotlin 不像 Java 那样区分原始类型和包装类型,所有的数值类型都是对象。但是,为了性能考虑,Kotlin 在后台会自动处理这些类型的特殊优化,使得它们的行为类似于 Java 的原始类型。

8.匿名函数

  • 定义时不取名字的函数,我们称之为匿名函数,匿名函数通常整体传递给其他函数,或者从其他函数返回。
kotlin 复制代码
fun main() {
    val total = "Mississippi".count()
    val count = "Mississippi".count { it == 's' }
    println(total)
    println(count)
}

9.函数参数

和具名函数一样,匿名函数可以不带参数,也可以带一个或者多个任何类型的参数,需要带参数时,参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中。

kotlin 复制代码
 val blessingFunction:(String) -> String = { name ->
        val holiday = "New Year"
        "Happy $holiday $name"
    }

    println(blessingFunction("Jack"))

10.it关键字

定义只有一个参数的匿名函数时,可以使用it关键字来表示参数名。当你需要传入两个值参,it关键字就不能用了。

11.匿名函数的类型推断

定义一个变量时,如果已把匿名函数作为变量复制给它,就不需要显示指明变量类型。

kotlin 复制代码
    val blessingFunction = {
        val holiday = "New Year"
        "Happy $holiday"
    }

    println(blessingFunction())

类型推断也支持带参数的匿名函数,但为了帮助编译器更准确地推断变量的类型,匿名函数的参数名和参数类型必须有。

kotlin 复制代码
    val blessingFunction:(String,Int)-> String = { name:String,year:Int ->
        val holiday = "New Year"
        "$year $name Happy $holiday"
    }
    val blessingFunction = { name:String,year:Int ->
        val holiday = "New Year"
        "$year $name Happy $holiday"
    }

12.lambda

Lambda 表达式的完整语法形式如下:

kotlin 复制代码
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
  • lambda 表达式总是括在花括号中。
  • 完整语法形式的参数声明放在花括号内,并有可选的类型标注。
  • 函数体跟在一个 -> 之后。
  • 如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个)表达式会视为返回值。
kotlin 复制代码
val sum = { x: Int, y: Int -> x + y }

定义参数是函数的函数,如果一个函数的lambda参数排在最后,或者是唯一参数,那么括住lambda值参的一对圆括号可以省略

kotlin 复制代码
fun main() {

    val getDiscountWords = {goodsName : String,hour : Int ->
        val  currentYear = 2024
        if (hour > 12){
            "Discount for $goodsName in $currentYear $hour"
        }else{
            "No Discount for $goodsName in $currentYear $hour"
        }
    }

    showOnBoard("iPhone"){ goodsName,hour ->
        val  currentYear = 2024
        if (hour > 12){
            "Discount for $goodsName in $currentYear $hour"
        }else{
            "No Discount for $goodsName in $currentYear $hour"
        }
    }
}


fun showOnBoard(goodsName:String , getDiscountWords:(String,Int) -> String){
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName,hour))
}

13.函数内联

内联(inline)函数是一种特殊的函数,它允许编译器将函数的调用处直接替换为函数体的代码。这种方式可以消除函数调用的开销,并且对于一些高阶函数(即接受其他函数作为参数或返回其他函数的函数)特别有用,因为它们通常会创建闭包对象来存储 lambda 表达式的上下文。

为什么使用内联?

  • 性能提升:通过消除函数调用的开销,尤其是当函数非常小的时候,内联可以提高程序的执行效率。
  • 非局部返回:内联函数中可以使用 return 直接从外部作用域返回,这在普通的函数中是不允许的。
  • 重载解析:内联函数可以在被调用时进行更精确的类型推断,从而影响到方法重载的选择。
  • 减少闭包对象的创建:当传递 lambda 表达式给函数时,如果没有内联,lambda 会被包装成一个对象。内联则可以直接将 lambda 的代码插入到调用处,避免了这种开销。

13.函数引用

函数引用是一种将函数本身作为值传递给其他代码的方式。这使得你可以像处理任何其他值一样处理函数,例如将它们存储在变量中、作为参数传递或从函数返回。Kotlin 提供了简洁的语法来创建函数引用,并且这些引用可以用于各种场景,比如与高阶函数一起使用。

函数引用的基本形式:创建一个函数引用,你只需要使用 :: 操作符加上函数名。

kotlin 复制代码
fun main() {

    showOnBoard("Laptop",::getDiscountWords)
}

private fun getDiscountWords(goodsName: String,hour:Int) : String {
    val  currentYear = 2024
    return if (hour > 12){
        "Discount for $goodsName in $currentYear $hour"
    }else{
        "No Discount for $goodsName in $currentYear $hour"
    }
}


private fun showOnBoard(goodsName:String , getDiscountWords:(String,Int) -> String){
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName,hour))
}

14.高阶函数

函数类型也是有效的返回类型,也就是说可以定义一个能返回函数的函数。

kotlin 复制代码
fun main(){
    val getDiscountWords: (String) -> String = configDiscountWords()
    println(getDiscountWords("Apple"))
}

fun configDiscountWords() : (String) -> String {

    return { goodsName ->
        val  currentYear = 2024
        val hour = (1..24).shuffled().last()
        if (hour > 12){
            "Discount for $goodsName in $currentYear $hour"
        }else{
            "No Discount for $goodsName in $currentYear $hour"
        }
    }
}

15.闭包

在Kotlin中,匿名函数能修改并引用定义在自己作用域之外的变量,匿名函数引用着定义自身的函数里的变量,在Kotlin中的lambda就是闭包。

kotlin 复制代码
fun createCounter(): () -> Int {
    var count = 0  // 定义一个可变的局部变量
    return {
        count++  // lambda 捕获了 count 变量
    }
}

val counter = createCounter()
println(counter())  // 输出 1
println(counter())  // 输出 2

在这个例子中,createCounter 函数返回一个 lambda 表达式,该表达式每次调用时都会增加 count 的值。尽管 count 是在 createCounter 内部定义的局部变量,但返回的 lambda 仍然可以访问它,这就是闭包的作用。

注意事项:

  • 性能考虑:闭包可能会导致额外的内存开销,因为需要保持对捕获变量的引用。如果捕获的是大对象或大量数据,这可能会影响性能。
  • 变量捕获:在 Kotlin 中,lambda 表达式只能捕获那些在创建时就已经声明为 val 或 var 的变量。如果你尝试捕获一个没有初始化的变量,编译器会报错。
  • 不可变性:为了保证线程安全,通常建议只捕获不可变的数据。如果确实需要捕获可变状态,确保正确处理并发问题。
相关推荐
景天科技苑4 分钟前
【Golang】Go语言中如何进行包管理
开发语言·后端·golang·go mod·go语言包管理·go包管理·go sum
wwangxu7 分钟前
Java 面向对象基础
java·开发语言
Patience to do16 分钟前
Android Studio项目(算法计算器)
android·算法·android studio
wdxylb22 分钟前
Linux下编写第一个bash脚本
开发语言·chrome·bash
幽兰的天空25 分钟前
Python实现的简单时钟
开发语言·python
这题怎么做?!?32 分钟前
模板方法模式
开发语言·c++·算法
幽兰的天空1 小时前
简单的Python爬虫实例
开发语言·爬虫·python
冷眼看人间恩怨1 小时前
【Java】揭秘网络编程:深入探索其无尽奥秘与魅力
java·开发语言·tcp/ip·udp·tcp
※※冰馨※※1 小时前
Unity3D 鼠标移动到按钮上显示信息
开发语言·unity·c#
Algorithm15762 小时前
JVM是什么,与Java的关系是什么,以及JVM怎么实现的跨平台性
java·开发语言·jvm