Kotiln基础语法总结

编程入门 行业动态 更新时间:2024-10-11 11:18:48

Kotiln基础<a href=https://www.elefans.com/category/jswz/34/1770552.html style=语法总结"/>

Kotiln基础语法总结

kotlin不仅支持编写在虚拟机上运行,而且还是一门跨平台的通用型语言,我们可以用Kotlin开发各种类型的原生应用,如Android,macOS,Windows,Javascript应用。

Kotlin能脱离虚拟机层,直接编译成可以在Windows,Linux和macOS平台上运行的原生二进制代码。

一、变量


变量声明

//Int类型可以省略,自动推导
var max: Int = 5
//var 可读可写
//val 可读不可写

常用内置数据类型

类型描述示例
String字符串”Hello World“
Char单字符‘A’
Booleantrue/falsetrue false
Int整数5
Double小数3.14
List元素集合
Set无重复元素的集合
Map键值对集合

二、编译时常量


编译时常量只能在函数之外定义,因为编译时常量必须在编译时赋值,而函数都是在运行时才调用,函数内的变量也是在运行时赋值,编译时常量要在这些变量赋值前就已存在
编译时常量只能时常见的基本数据类型:String、Int、Double、Float、Long、Short、Byte、Char、Boolean

const val MAX = 100

三、查看Kotlin字节码


两种方式
1.Shift键两次,输入Show Kotlin
2.Tools->Kotlin->Show Kotlin Bytecode


Decompile可以反编译成java代码

四、Kotlin的引用类似与基本数据类型


Java有两种数据类型:引用类似与基本数据类型
Kotlin只提供引用类型这一种数据类型,出于更高性能的需要,Kotlin的编译器会在Java字节码中引用基本数据类型

五、range表达式


//range
val age = 0
//0 .. 3  大于等于0小于等于3
if(age in 0 .. 3){println("婴幼儿")
//4 .. 12  大于等于4小于等于12
}else if(age in 4 .. 12){println("少儿")
}else{println("青少年")
}//其他写法
if(age !in 0 .. 3){}else{}

range表达式是闭区间

六、when表达式


 //whenval school = "小学"when(school){"学前班" -> "幼儿园""小学" -> "少儿""中学" -> "青少年"else ->{println("未知")}}

允许你编写条件式,在某个条件满足时,执行相应的代码。只要代码包含else if分支,都建议改用when表达式。

七、string模板


模板支持在字符串的引号内放入变量值,还支持字符串里计算表达式的值并插入结果,添加在${} 中的任何表达式,都会作为字符串的一部分求值。

//String模板 StringTemplate
val orgin = "Jack"
val dest = "Rose"
println("$orgin love $dest")val flag = true
println("Answer is ${if(flag) "我可以" else "对不起"}")

八、函数


可见修饰符默认是public

8.1、函数参数

默认参数
如果不打算传入值参,可以预先给参数指定默认值

具名函数参数
如果使用命名值参,就可以不用管值参的顺序

private fun doSomething(age: Int, flag: Boolean): String{return "result"
}//函数可以加默认值
fun fix(name: String, age: Int = 2){println(name + age)
}fun main(){doSomething(flag = false, age = 12)
}

8.2、Unit函数

不是所有函数都有返回值,Kotlin中没有返回值的函数叫Unit函数,也就是说他们的返回类型是Unit。在Kotlin之前,函数不返回任何东西用void描述,意思是“没有返回类型,不会带来什么,忽略它”,也就是说如果函数不反悔任何东西,就忽略类型。但是,void这种解决方案无法解释现代语言的一个重要特征,泛型。

8.3、TODO函数

TODO函数的任务就是抛出异常,就是永远别指望它运行成功,返回Nothing类型

public inline fun TODO(): Nothing = throw NotImplementedError()

8.4、反引号的函数名

Kotlin可以使用空格和特殊字符对函数命名,不过函数名要用一对反引号括起来
为了支持Kotlin和Java互操作,而Kotlin和Java各自却有着不同的保留关键字,不能作为函数名,使用反引号括住函数名就能避免任何冲突

fun `is`(){}

九、匿名函数


定义时不取名字的函数,我们称之为匿名函数,匿名函数通常整体传递给其他函数,或者从其他函数返回

匿名函数对Kotlin来说很重要,有了它,我们能够根据需要制定特殊规则,轻松定制标准库里的内置函数

	//如果一个函数的lambda参数排在最后,或者是唯一的参数,那么括住lambda值参的一对圆括号就可以省略//字符串中s的个数val total = "Mississipi".count({letter -> letter == 's'})println(total)

匿名函数也有类型,匿名函数可以当作变量赋值给函数变量,就像其他变量一样,匿名函数就可以在代码里面传递了。

和具名函数不一样,除了极少数情况外,匿名函数不需要return关键字来返回数据,匿名函数会隐式或自动返回函数体最后一行语句的结果。

//声明一个变量,等于一个函数,就是函数的类型
//函数的类型由参数和返回值决定
val blessingFunction: ()->String = {val holiday = "New Year.""Happy $holiday"
}
println(blessingFunction())//传一个参数的时候,name参数可以用it替代
val blessingFunction2: (String)->String = {name ->"Happy $name"
}
println(blessingFunction2("New Year"))//返回值类型推断
val blessingFunction3 = {name: String ->"Happy ${name}"
}
println(blessingFunction3("New Year"))

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

9.1、lambda

我们将匿名函数称为lambda,将它的定义成为lambda表达式,它返回的数据称为lambda结果。

十、定义参数是函数的函数


函数的参数是另外一个函数

//显示促销的文案,文案由另外一个函数生成
fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String){val hour = (1..24).shuffled().last();println(getDiscountWords(goodsName, hour))}fun test03(){val getDiscountWords = { goodsName: String, hour: Int ->val currentYear = 2027"${currentYear}年, 双11${goodsName}促销倒计时:$hour 小时"}showOnBoard("卫生纸", getDiscountWords)}//第二种写法  简略写法
showOnBoard("卫生纸"){ goodsName: String, hour: Int ->val currentYear = 2027"${currentYear}年, 双11${goodsName}促销倒计时:$hour 小时"
}

闭包是为了解决作用域问题

十一、函数内敛(inline)


在jvm上,你定义的lambda会以对象实例的形式存在,jvm会为所有同lambda打交道的变量分配内存,这就是内存开销。更糟的是,lambda的内存开销会带来严重的性能问题。幸运的是,kotlin有一种优化机制叫内敛,有了内敛,jvm就不需要使用lambda对象实例了,因而避免了变量内存分配。哪里需要使用lambda,编译器就会将函数体复制粘贴到哪里。

使用lambda的递归函数无法内敛,因为会导致粘贴无限循环,编译会发出警告。

十二、函数引用


fun getDiscountWords(goodsName: String, hour: Int): String{val currentYear = 2027return "${currentYear}年, 双11${goodsName}促销倒计时:$hour 小时"
}//显示促销的文案,文案由另外一个函数生成
fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String){val hour = (1..24).shuffled().last();println(getDiscountWords(goodsName, hour))}showOnBoard("卫生纸", ::getDiscountWords)

十三、闭包


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

能接受函数或者返回函数的函数又叫高级函数,高级函数广泛应用于函数式编程当中

//闭包
fun configDiscountWords(): (String) -> String{return {goodsName: String ->val currentYear = 2027val hour = (1..24).shuffled().last();"${currentYear}年, 双11${goodsName}促销倒计时:$hour 小时"}}val getDiscountWords = configDiscountWords()
println(getDiscountWords("牙膏"))

函数类型能让开发者少写模式化代码,写出更灵活的代码。java8支持面向对象编程和lambda表达式,但不支持将函数作为参数传给另一个函数或变量,不过java的替代方案是匿名内部类。

十四、null


kotlin更多地把运行时可能会出现的null问题,以编译时错误的方式,提前在编译期强迫我们重视起来,而不是等到运行时报错,防范于未然,提高了我们程序的健壮性。

对于null值问题,Kotlin反其道而行之,除非另有规定,变量不可为null值,这样一来,运行时崩溃从根源上得到解决。

var str: String = "abc"
str = null //编译报错var str2: String? = readLine()
str2 = null

Kotlin区分可空类型和非可空类型,所以,你要一个可空类型变量运行,而它又可能不存在,对于这种潜在危险,编译器时刻警惕着,为了应对这种风险,kotlin不允许你在可空类型上调用函数,除非你手动接手安全管理。

三种类型操作空值

  • 选项一:安全调用操作符?.

如果遇到null值,它就跳过函数调用,而不是返回null。

var str2: String? = readLine()?.capitalize()
  • 使用非空断言操作符 !!.

  • 使用if判断

十五、空合并操作符 ?:


如果左边的求职结果为null,就使用右边的结果值

var str: String? = str?: "butterfly"

十六、异常


//自定义异常
class UnskilledException(): IllegalStateException("操作不合法"){}fun checkOperation(number: Int?){number ?: throw UnskilledException()
}fun testException(){var number: Int? = null//处理异常try {number!!.plus(1)}catch (e: Exception){println(e)}}

十七、先决条件函数


Kotlin标准库提供了一些便利函数,使用这些内置函数,你可以抛出带自定义信息的异常,这些便利函数叫做先决条件函数,你可以用它定义先决条件,条件必须满足,目标代码才能执行

kotlin都是运行时异常(未检查异常),可以不try catch,非运行异常(检查异常)都是通过编译器报错来处理的。

十八、字符串操作


18.1、substring

字符串截取,substring函数支持IntRange类型(表示一个函数范围的类型)的参数,until创建的范围不包括上限值

val name = "Jimmy's friends"
val index = name.indexOf('\'')
//支持IntRanger
val str = name.substring(0 until index)

18.2、split和解构赋值

split函数返回的是List集合数据,List集合又支持解构语法特性,它允许你在一个表达式里给多个变量赋值,解构常用来简化变量的赋值。

//解构赋值
val name = "Jimmy,friends,hello"
val (a, b, c) = name.split(',')
println("$a,$b,$c")

18.2、replace 字符串替换

val name = "Jimmy,friends,hello"
val str = name.replace(Regex("[aeiou]")) {when(it.value){"a" -> "8""e" -> "4"else ->it.value}
}
println(str)

18.3、字符串比较

在kotlin中,用==检查两个字符串中的字符是否匹配,用===检查两个变量是否指向堆上同一个对象,而在Java中==做引用比较,做结构比较时用equals方法。

val str1 = "Jack"
val str2 = "Jack"
println(str1 == str2) //true
println(str1 === str2) //trueval str1 = "Jack"
val str2 = "jack".capitalize()
println(str1 == str2) //true
println(str1 === str2) //false

18.4、forEach

val name = "Jimmy,friends,hello";
name.forEach {println("$it*")
}

十九、数字类型


和Java一样,Kotlin中所有数字类型都是有符号的,也就是说既可以表示正数,也可以表示负数

19.1、安全转换函数

kotlin提供了toDoubleOrNulltoIntOrNull这样的安全转换函数,如果数值不能正确转换,与其触发异常不如干脆返回null值

val number:Int? = "8.98".toIntOrNull() //null

19.2、Double类型格式化

格式化字符串是一串特殊字符,它决定该如何格式化数据。

//8.99 会四舍五入
val s = "%.2f".format("8.987899")
//精度损失
val number2:Int? = 8.98.toInt()
//四舍五入
val number3:Int? = 9.98.roundToInt()

二十、标准库函数

20.1、apply

apply函数可看作一个配置函数,你可以传入一个接收者,然后调用一系列函数来配置它以便使用,如果提供lambda给apply函数执行,它会返回配置好的接收者

val file = File("D://I have a dream_copy.txt")
file.setReadable(true)
file.setWritable(true)
file.setExecutable(false)val file2 = File("D://I have a dream_copy.txt").apply {setReadable(true)setWritable(true)setExecutable(false)}

可以看到,调用一个个函数类配置接收者时,变量名就省掉了,这是因为,在lambda表达式里,apply能让每个配置函数都作用于接收者,这种行为有时又叫做相关作用域,因为lambda表达式里的所有函数调用都是针对接收者的,或者说,它们是针对接收者的隐式调用。

20.2、let函数

let函数能使某个作用于其lambda表达式里,让it关键字能引用它。let与apply比较,let会把接收者传给lambda,而apply什么都不传,匿名函数执行完,apply会返回当前接收者,而let会返回lambda的最后一行。

val result = listOf(3, 2, 1).first().let { it * it }

20.3、run函数

run和apply差不多,但与apply不同,run函数不返回接收者,run返回的是lambda结果,也就是true或者false。

 val file = File("D://I have a dream_copy.txt")file.run {readText().contains("great")}val flag:Boolean = "I have a dream_copy".run(::isTooLong)//链式调用写法"I have a dream_copy".run(::isTooLong).run(::showMessage).run(::println)

20.4、with函数

with函数是run的变体,他们的功能行为是一样的,但with的调用方式不同,调用with时需要值参作为其第一个参数传入。

with("I have a dream_copy"){length > 0
}

20.5、also

also函数和let函数功能相似,和let一样,also也是把接收者作为值参传给lambda,但有一点不同:also返回接收者对象,而let返回lambda结果。因为这个差异,also尤其适合针对同一原始对象,利用副作用做事,既然also返回的是接收者对象,你就可以基于原始接收者对象执行额外的链式调用。

var fileContents: List<String>File("D://I have a dream_copy.txt").also {println(it.name)}.also { fileContents = it.readLines()}println(fileContents)

20.6、takeIf

和其他标准函数有点不一样,takeIf函数需要判断lambda中提供的条件表示式,给出true或false结果,如果判断结果式true,从takeIf函数返回接收者对象,如果式false,则返回null。如果需要判断某个条件是否满足,再决定是否可以赋值变量或执行某项任务,takeIf就非常有用,概念上讲,takeIf函数类似于if语句,但它的优势是可以直接在对象实例上调用,避免了临时变量赋值的麻烦。

var fileContents = File("D://I have a dream_copy.txt").takeIf { it.exists() }?.readText()

20.7、takeUnless

takeIf辅助函数takeUnless,只有判断你给定的条件结果是false,takeUnless才是返回原始接收者对象。

var fileContents = File("D://I have a dream_copy.txt").takeUnless { it.isHidden }?.readText()

二一、List


getOrElse是一个安全索引取值函数,它需要两个参数,第一个是索引值,第二个是能提供默认值的lambda表达式,如果索引值不存在的话,可用来代替异常。

getOrNull是Kotlin提供的另一个安全索引取值函数,它返回null结果,而不是抛出异常。

//list集合 只读
val listOf = listOf("Jason", "Jack", "Jacky").distinct() //distinct去重
//越界了不会抛异常,而是可以交给lambda处理
listOf.getOrElse(4){"UnKnow"}
listOf.getOrNull(4)?: "UnKnow"
listOf.toMutableList()//可写
val mutableListOf = mutableListOf("Jason", "Jack", "Jacky")
mutableListOf.add("Jimmy")
mutableListOf.remove("Jimmy")
mutableListOf += "Jimmy"
mutableListOf -= "Jimmy"
mutableListOf.toList()

21.1、mutator函数

能修改可变列表的函数有个统一的名字:mutator函数
添加元素运算符与删除元素运算符
基于lambda表达式指定的条件删除元素

21.2、集合遍历

for in遍历
forEach遍历
forEachIndexed遍历时要获取索引

val listOf = listOf("Jason", "Jack", "Jacky").distinct() //distinct去重
listOf.forEach{println(it)
}
listOf.forEachIndexed{index, item ->//带索引println("$index $item")
}

21.4、解构

通过_符号过滤不想要的元素

val (origin, _, proxy) = listOf("Jason", "Jack", "Jacky").distinct() //distinct去重

二二、set


通过setOf创建set集合,使用elementAt函数读取集合中的元素

//只读
val set = setOf("Jack", "Jason", "Jacky")
set.elementAt(1)//可写
val mutableSetOf = mutableSetOf("Jack", "Jason", "Jacky")
mutableSetOf += "Kit"//快捷函数去重
listOf("Jason", "Jack", "Jack", "Jacky").distinct() //去重

22.1、数组类型

Kotlin提供各种Array,虽然是引用类型,但可以编译成Java基本数据类型

val intArrayOf = intArrayOf(10, 30, 40, 20)
listOf(10, 20, 30).toIntArray()
val arrayOf = arrayOf(File("xx"))

二三、map


to看上去像关键字,但事实上,它是个省略了点号和参数的特殊函数,to函数将它左边和右边的值转换成一对Pair。

//只读
val mapOf = mapOf("Jack" to 18, "Jo" to 20, "Ka" to 30)
//可变
val mutableMapOf = mutableMapOf("Jack" to 18, "Jo" to 20, "Ka" to 30)
mutableMapOf += Pair("Jas", 18)
mutableMapOf.put("Jimmy", 31)
mutableMapOf.getOrPut("Jac"){18}

23.1、读取Map的值

[]取值运算符,读取键对应的值,如果键不存在就返回null
getValue,读取对应的值,如果键不存在就抛出异常
getOrElse,读取键对应的值,或者使用匿名函数返回默认值
getOrDefault,读取键对应的值,或者返回默认值

mapOf.getValue("Jimmy")
mapOf.getOrElse("Jimmy"){10}
mapOf.getOrDefault("Jimmy", 10)mapOf.forEach{println("${it.key}, ${it.value}")
}mapOf.forEach{(key, value) ->println("${key}, ${value}")
}

二四、field


针对你定义的每一个属性,Kotlin都会产生一个field,一个getter、以及setter,field用来存储属性数据,你不能直接定义field,Kotlin会封装field,保护它里面的数据,只暴露给getter和setter使用。属性的getter方法决定你如何读取属性值,每个属性都有getter方法,setter方法决定你如何给属性赋值,所以只有可变属性才有setter方法,尽管Kotlin会自动提供默认的getter和setter方法,但在需要控制如何读写属性数据时,你也可以自定义他们。

class Player{var name = "abc"get() = field.capitalize()set(value) {field = value.trim()}var age = 10get() = field.absoluteValueset(value) {field = value.absoluteValue}//计算属性是通过一个覆盖的get或set运算符来定义,这时field就不需要了val rolledValue//每次都是变动的get() = (1..6).shuffled().first()}

更多推荐

Kotiln基础语法总结

本文发布于:2024-03-06 15:27:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1715677.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:语法   基础   Kotiln

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!