文章目录
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 的变量。如果你尝试捕获一个没有初始化的变量,编译器会报错。
- 不可变性:为了保证线程安全,通常建议只捕获不可变的数据。如果确实需要捕获可变状态,确保正确处理并发问题。