KOTLIN:
继承java特性:谷歌支持kotlin,java新的功能冗余。kotlin在移动应用平台开发越来越重要,对于Android开发KOTLIN必须掌握。新的特性会在kotlin进行更新。
2.kotlin基本数据:
声明变量:var maintopp :int = 5;
字符类型:单字符:Char:字符串:String。
Boolean:true/false:int:整数。Double:小数。List:元素集合。Set:无重复元素的集合:Map:键值对集合。
声明可修改变量:使用var 关键字,声明只读变量:使用val关键字。常量在头文件位置进行定义:const val Max = 100;
val name :String = “Jack”;var hello : String = “I love you”;
对于已经声明的类型变量,允许你不再次写类型:val name : = “Jack”;对于直接赋值的变量会直接类型推断。
编译时常量:只读变量并非绝对只读。编译时常量只能再函数之外定义,因为在编译时常量必须在编译时赋值,而函数都是在运行时调用的,函数内的变量也是在运行时赋值,编译时常量要在这些变量赋值前就已经存在。编译时常量只能是基本数据类型:String,Int,Double,Float,Long,Short,Byte,Char,Boolean。变量名全部大写开头:
fun main() {
var name = "hello word"
println(name)
var sin = "hdkhfnsjf"//赋值时进行类型推断//
println(sin)
}
shift两次,输入Show kotlin查看kotlin的字节源码》
java中分为引用类型和基本数据类型,kotlin中只有引用类型,为了提高效率kotlin会在字节码中将引用类型转为基本数据类型。
引用类型会放入堆空间,太多的引用类型放入堆空间会影响程序运行效率。
in A..B在大于A小于等于B的范围内,返回true或者Flase:when语句替代(java)switch语句
String模板:模板支持在字符串的引号内放入变量值,还支持字符串里计算表达式的值并插入结果,添加在${}中的任何表达式,都会作为字符串的一部分求值。
函数声明:
如果不打算传参,可以预先给参数指定默认值,如果使用命名传参,就可以不用管值参的顺序:
fun fix(name:String , age : Int = 2)//就是默认值,不传参就是用默认值
Unit函数:Kotlin中没有返回值的函数叫做Unit函数,也就是说他们的返回值类型为Unit。在Kotlin之前,函数不返回任何东西用void描述,也就是说如果函数不返回任何值就忽略类型。但是void无法解释现代语言的一个重要特征:泛型。
Nothing类型TODO函数的任务就是抛出异常,就是永远别指望它运行成功,返回Nothing类型。
反引号中的函数名:
Kotlin可以使用空格和特殊字符对函数命名,不过函数名要用一对反引号括起来。为了支持Kotlin和java互操作,而Kotlin和java各自却有着不同的保留关键字,不能作为函数名,使用反括号括住函数名就能避免任何冲突。
匿名函数:定义时不取名字的函数,匿名函数通常整体传递给其他函数,或者从其他函数返回。根据需要定制特殊规则,定制标准库里的内置函数。
函数类型与隐式返回:
匿名函数也有类型,匿名函数可以当作变量赋值给函数类型变量,就像其他变量一样,匿名函数就可以在代码里传递。和具名函数不同,处理极少数情况外,匿名函数不需要return关键字来返回数据,匿名函数会隐式或自动返回函数最后一行语句的结果。
函数参数:
和具名函数一样,匿名函数可以不带参数,也可以带一个或多个任何类型的参数,需要带参数时,参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中。
It关键字:
定义一个只有一个参数的匿名函数时,可以使用it关键字来表明参数名。当你需要传入两个值的参数时,it关键字就不能用。
定义一个变量时,如果已经将匿名函数作为变量赋值给它,就不需要显式指明变量类型。
/* val bless = { val hoilday = "new year" "happy $hoilday" }*/
类型推断:
lambda表达式:
定义参数是函数的函数:函数的参数是另一个函数。
如果一个函数的lambda参数排在最后,或者是唯一的参数,那么括住lambda值参的一对圆括号可以省略。
匿名函数闭包可以解决作用域问题。
函数内联:
在JVM上,定义的lambda会以对象实例的形式存在,JVM会为所有同lambda打交道的变量分配内存,产生了内存开销,lambda的内存开销会带来严重的性能问题,在Kotlin中提供了优化机制叫做内联,在内联情况下,JVM就不需要使用lambda对象实例,从而避免变量内存分配,在使用lambda的地方编译器会自动将函数体复制去,使用lambda的递归函数无法内联,因为会导致复制粘贴的无限循环,编译会发出警告。
函数引用:
要将函数作为参数传递给其他函数使用,除了传递lambda表达式,kotlin还提供了其他的方法,传递函数引用,函数引用可以把一个具名函数转换成一个值参,使用lambda表达式的地方,都可以使用函数引用。
函数作为参数返回:
函数类型作为返回类型,也就是定义一个可以返回函数的函数。
闭包:
在kotlin中,匿名函数能修改并引用定义在自己作用域之外的变量,匿名函数引用着定义自身的函数里的变量,kotlin中的lambda就是闭包。
能接收函数或者返回函数的函数又叫做高级函数,高级函数广泛应用于函数式变成当中。
null安全与异常:
null:kotlin更多把可能会出现的空指针异常问题在编译器提前警示,减少运行时错误,对于null值问题,除非另有规定,否则变量不可以为null值。
Kotlin区分可空类型与非可空类型,所以,如果要一个可空类型变量运行,而他又可能不存在,对于这种危险,编译器时刻警惕着。为了应对这种风险,Kotlin不允许你在可空类型值上调用函数,除非你主动接手管理。
对null进行操作:(?)
安全调用操作符:Kotlin不会报错,编译器发现有安全调用操作符,所以他会知道如何去检查null值。如果遇到null值,她就跳过函数调用,而不是返回null。
使用带let的安全调用:(!!和?可以进行null操作)
安全调用允许在可空类型上调用函数,但是如果向进行额外操作,比如创建新值,或者判断不为null就调用其他函数,可以使用带let的安全操作符,可以在任何类型上调用let函数,它的主要作用是让你在指定的作用域内定义一个或多个变量。
使用非空断言操作符:
!!感叹号操作符,当变量值为null时,会抛出KotlinNullPointerException。
使用if判断null情况:可以使用if判断,调用安全操作符使用更加灵活,代码更简洁,安全操作符可以进行多个函数的链式调用。
空合并操作符:(?:)操作符为:如果左边的求值结果为null,就使用右边的结果值。
空合并操作符也可以和let函数一起来使用代替if/else/语句。(elvis)
异常:
先决条件函数:Kotlin标准库提供了一些便利函数,使用这些内置函数,你可以抛出带自定义信息的异常,这些便利函数叫做先决函数,你可以用它定义先决条件,条件必须满足目标代码才能执行。
String:
字符串的截取,substrring函数支持IntRange类型(表示一个整数范围的类型)的参数,until创建的范围不包括上限值。
const val NAME = "Jimmy's friend"
fun main() {
val index : Int = NAME.indexOf('\'')
val str : String = NAME.substring(0 until index)
println(str)
}
split:
spilt函数返回的是List集合数据,List集合又支持解构语法特性,它允许你在一个表达式里给多个变量赋值,解构常用来简化变量的赋值。
析构函数,用于在C++中释放堆内存。
const val Name = "jack,jacky,jason"
fun main() {
val data = Name.split(',')
//解构赋值
val (origin,dest,proxy) = Name.split(",")
println("$origin $dest $proxy")
}
replace:
字符串替换:
fun main() {
val str = "The people's Republic of China."
val str1 = str.replace(Regex("[aeiou]")){
when(it.value){
"a" -> "8"
"e" -> "6"
"i" -> "9"
"o" -> "1"
"u" -> "3"
else -> it.value
}
}
println(str)
println(str1)
}
字符串比较:
在Kotlin里面我们用==比较两个字符串中的字符是否匹配,用===检查两个变量是否指向内存堆上同一个对象,而在JAVA中==作为引用比较,做结构比较时用equals方法。
fun main() {
//字符串不可变,new。字符串常量池
val str1 = "jack"
val str2 = "jack"
println("$str1 str2")
println(str1 == str2)
println(str1 === str2)
}
fun main() {
//字符串不可变,new。字符串常量池
val str1 = "Jack"
val str2 = "jack".capitalize()
println("$str1 str2")
println(str1 == str2)
println(str1 === str2)
}
fun main() {
//字符串不可变,new。字符串常量池
val str1 = "Jack"
val str2 = "jack"
str2.capitalize()
println("$str1 str2")
println(str1 == str2)
println(str1 === str2)
}
foreach:
遍历字符:
fun main() {
"The prople China".forEach {
print("$it")
}
}
数字类型同java
安全转换函数:Kotlin提供了toDoubleOrNull和toIntOrNull这样的安全转换函数,如果数值不能正确转换,不会触发异常而会返回null值
标准函数:
apply:apply函数可以看作一个配置函数,你可以传入一个接收者,然后调用一系列的函数来配置它,以便于使用,如果提供lambda给apply函数执行,他会返回配置好的接收者。
import java.io.File
fun main() {
val file1 = File("D:\\管理员密码.txt")
file1.setReadable(true)
file1.setWritable(true)
file1.setExecutable(false)
val file2 = File("D:\\管理员密码.txt").apply {//隐式this
setReadable(true)
setWritable(true)
setExecutable(false)
}
}
调用一个个函数类配置接受者时,变量名就省略掉了,这是因为,在lambda表达式中,apply能让每个配置函数都做用于接受者,这种行为有时又叫做相关作用域,因为lambda表达式里所有的函数调用都是针对接收者的,或者说他们是针对接受者的隐式调用。
let函数:
let函数能使某个变量作用于其lambda表达式里,用it关键字能引用它。let与apply比较,let会把接收者传给lambda,而apply不会传入任何东西,匿名函数执行完,apply会返回当前接收者,而let会返回lambda的最后一行。
fun main() {
val re = listOf(3,2,1).first().let {
it * it
}
val ji = listOf(3,2,1).first()
val re2 = ji * ji
println(format2(null))
println(format2("aisheshe"))
}
fun format(getName:String?):String{
return getName?.let {
"welcome,$it."
} ?:"what's your name?"
}
fun format2(getName:String?):String{
return if(getName != null){
"welcome,$getName"
}else{
"what's your name?"
}
}
run:
只看作用域,run与apply差不多,但与apply不同,run函数不返回接收者,run返回的是lambda结果,也就是true或者false。
with:
with函数是run函数的变体,他们的功能行为是一样的,但with的调用方式不同,调用with时需要值参作为第一个参数传入。
also:
also函数和let函数的功能相似,和let函数一样,also也是把接收者作为值参传给lambda,但是also返回接收者对象,而let返回lambda结果。这个差异also更适合针对同一原始对象,利用副作用做事,also返回的是接收者对象,我们可以基于原始接收者对象执行额外的链式操作调用。
fun main() {
val fileContent: List<String>
File("D:\\管理员密码.txt")
.also{
println(it.name)
}.also {
fileContent = it.readLines()
}
println(fileContent)
}
takeif:
takeif函数需要判断lambda中提供的条件表达式,给出true或false结果,如果判断结果是true,从takeif函数返回接收者对象,如果是false,则返回null,如果需要判断某个条件是否满足,再决定是否可以赋值变量或执行某项任务,takeif函数类似于if语句,它可以直接在对象实例上调用,避免了临时变量赋值的麻烦。
List:
getOrElse是一个安全索引取值函数,需要两个参数,第一个为索引值第二个是能提供默认值的lambda表达式,如果索引值不存在,会用来替代异常。
getOrNull是kotliin提供的另一个安全索引取值函数,他返回null结果,而不是抛出异常。
fun main() {
val list = listOf("wsx","zst","ass")
println(list.getOrElse(4){"Unknown"})
println(list.getOrNull(4)?:"Unknown")
}
在kotlin中,支持内容修改的列表叫做可变列表,要创建可变列表,可以使用mutable ListOf函数。list还支持使用toList和toMutableList函数动态实现只读列表和可变列表的相互转换。(元素的改变)。
fun main() {
val mutableList = mutableListOf("wsx","zst","lqq")
mutableList.add("jimmy")
mutableList.remove("wsx")
println(mutableList)
println(mutableList.remove("hj"))
listOf("1","2","3").toMutableList()
mutableList.toList()
}
mutator函数:
能修改可变列表的函数有一个统一的名称:mutator函数。
添加元素运算符与删除元素运算符(C++中的运算符重载)
基于lambda表达式指定的条件删除元素。
fun main() {
val mutatorl = mutableListOf("wsx","lqq","zst")
mutatorl += "jimmy"
mutatorl -= "wsx"
println(mutatorl)
// (C++运算符重载) 运算符赋予意义
mutatorl.removeIf{it.contains("lqq")}
println(mutatorl)
}
遍历集合:
forin,foreach,forEachIndexed遍历时要获取索引。
fun main() {
val mutatorList = mutableListOf("wsx","lqq","zst")
for (s in mutatorList) {
println(s)
}
mutatorList.forEach {
println(it)
}
mutatorList.forEachIndexed{
index,item->
println("$index,$item")
}
}
解构:
通过_符号过滤不想要的元素。
Set创建与元素的获取:
通过setOf创建set集合,使用elementAt函数读取集合中的元素。
fun main() {
val set = setOf("wsx","lqq","zst")
for (s in set) {
println(s)
}
println(set.elementAt(1))
val mutableSet = mutableSetOf("kotlin","wsx","plm")
mutableSet += "groy"
for (s in mutableSet) {
println(s)
}
println(listOf("jack","jason","jack").toSet().toList())
println(listOf("jack","jack","jack").distinct())
}
可变集合:通过mutableSetOf创建可变的set集合:集合转换:List转换成Set,去掉重复元素,快捷函数:
IntArray intArrayOf
DoubleArray doubleArrayOf
LongArray longArrayOf
ShortArray shortArrayOf
ByteArray byteArrayOf
FloatArray floatArrayOf
BooleanArray booleanArrayOf
Array arrayOf