数据类型
首字母大写
String Char Boolean Int Double list Set Map
“a” to 5,“b” to 6
String
${} 字符串模板
substring(0 until -1)
split返回 origin,dest,proxy,三个字符串,。也可以返回List,返回挨个赋值而已,有可能赋值没完?
replate(){when
forEach
==字符是否匹配
===是否同一对象。新生成的就不是一个字符串了
数字
没有转换成功就返回null而不是抛异常
字符串toInt就抛异常,toIntOrNull就不抛异常
Double转int不抛异常
const
编译时常量只能在函数之外,因为编译时厂里必须在编译时赋值,二函数都是在运行时才调用,函数内的便利也是运行时赋值,编译时常量要在这些变量赋值前就已存在。
const value MAX=5
函数
具名参数
匿名参数
没有返回值的函数叫Unit函数,返回类型是Unit。
Unit解决void无法解决泛型的解释问题
TODO永远别指望运行常规,返回Nothing类型,抛出异常x可以使用\
来表示特殊的函数名
匿名函数
没有名字的函数,匿名函数通常整体传递给其他函数
匿名函数会隐式或自动返回函数体最后一行语句的结果
// 变量的类型是匿名函数 // 无参,返回值类型为string
val func:()->String = {
val a="a"
"b"
}
// 需要带参数时,
val func:(String)->String = { name->
val a="a"
"b"
}
// it关键字
// 只有一个参数的匿名函数时,可以不写,用it代替
val func:(String)->String = {
val a="a"
"${it} $it b"
}
// 可以省略成 // 注意是a={}就行
val func = {
val a="a"
"${it} $it b"
}
// 多个参数时可以不在=左面写,但可以在右面name:String写
// 作为参数时,fun:()->String // 就是指定了参数和返回值
// 如果一个函数的lambda参数排在最后,或者是唯一的参数,name参数的一堆圆括号可以省略
// 传递参数的引用,可以用::fun // 可以使用lambda的地方都可以使用函数引用
// 函数作为返回值
// 匿名内部类,创建对象。
// 注意一下,第二个参数是匿名内部类时,可以把它提取到(){
}
函数内联
在JVM中,定义的lambda以对象实例的形式存在,产生了内存开销。而kotlin相当于DEFINE;但是使用lambda的递归函数无法内联,否则会无线赋值循环,变异会发出警告
show kotlin
闭包
匿名函数能修改自己作用域之外的便利,引用自己作用于里的就是闭包
lambda
演算
apply
标准库函数
是一个配置函数,传入接受者,然后调研一系列
调研一个个函数累配置接收者是,变量名就省略了,因为在lambda里apply能让每隔配置函数都作用于接受者,这种行为又是又叫做相关作用于,因为lambda表达式里的所有函数调研都是针对于接受者的,或者说是针对于接受者的隐式调用
let
ley会吧接受者传给lambda,二apply什么都不传,就是使用it然后返回
类
编译好的java文件名就是文件名,而且还是final的
嵌套类:如果一个类只对另外一个类有用
kotlin只提供引用类型这一数据类型,出于更性能的需要,kotlin编译器会在java字节码中改用基本数据类型
数据类:专门用来存储数据的类,toString方法
data class A(var x:Int,vat y:Int){}
此时打印的时候人家就已经写过toString方法了
hashCode和equals等方法 ==
Any超类的默认实现就是使用的=== ,二data类使用的是==
还提供了copy
var b = a.copy("name") // copy对应到了构造方法上
// 数据类还可以解构,解构的是主构造的属性
其实就是帮我们重写了
operator fun component1() = exprience
类似的,如果a+b想要支持,可以重载
operatiror fun puls(other:A)=A(x+other.x,y+other.y)
属性
针对你定义的每一个属性,kotlin都会产生一个field、一个getter以及一个setter。field同来存储属性,你不能直接定义field,kotlin会封装field,保护里面的数据,只暴露给getter、setter使用。
也可以自定义getter、setter
class P{
var name ="a"
get()=field.captitalize()
set(value){field=value.trim()}
var age =10
get()=field.absoluteValue
set(value){field=value.absoluteValue}
}
// 使用的时候p.name="a"就可以,编译会调用setter
getter setter要紧跟在属性后面写
计算属性可以不写field
构造
临时变量通常用_a表示。
可以在主构造函数里定义属性,不写_就是属性了
class P(
var _name:String
){
var name=_name
}
class P(
name:String
){
}
// 指定默认值
class P(
var name:String="A"
){
}
次构造函数
construct(name:String):this(name,age=10)
construct(name:String):this(name,age=10){
}
init
初始化块,可以检测某构造函数的值是否有效,
初始化块代码在构造累实例时执行
初始化顺序
- 主构造函数里什么的属性 // 就是参数
- 类级别的属性赋值 // {里面写的
- init里的属性赋值和函数调用 // init{里的
- 但是上面2个不是绝对的,顺序写反也报错
- 次构造函数里的赋值和函数调用 // 次构造函数首先调用了主构造函数,而前面3个都在主构造函数里
编译没问题不代表一定没问题,可能还会有未初始化就使用的潜在危险
延迟初始化lateinit
如果不想再构造时候初始化,name就可以使用延迟初始化
在用它之前负责初始化
class P{
lateinit var a:String
fun ready(){
a="a"
}
fun b(){
println(a)
}
// 只有调用了ready()才能调用b()
// 也可以在b中用if(::a.isInitialized)判断下再使用
}
惰性初始化by lazy
延迟初始化和惰性初始化不同
暂时不初始化某个变量,使用时再初始化
val a by lazy{func1()}
private func1():String{
return "a"
}
继承
累默认都是封闭的,要让某个类开放继承,必须使用open关键字修饰它
open class A:B("b"){}
类型转换
可以通过is检测是否是哪个类型的对象
- 通过as可以转换类型 a as B
- 只要使用过一次as,后面使用a时就智能转换了,不用再写as
- 所有类的超类是Any
object
使用object可以定义一个只能产生一个实例的类:单例
使用object的三种方式
- 对象声明:声明后直接用类名调研方法。可以定义在类内部,但不可以有构造器
- 对象表达式:匿名内部类,与java的区别在于可以调用非接口的方法
- 伴生对象:包级别函数
object A{
init{
}
fun func(){}
}
// 既是类名,又是实例对象名字
A.func()
半生对象
如果你想将某个对象的初始化和一个类实例捆绑到一起,可以考虑使用半生对象,使用companion修饰,一个类只能有一个伴生对象
本质上局部静态类
无论实例化多少次,伴生对象已有一个
open class A{
companion object{
private const val PATH="A"
fun func1()=FILE(PATH).readBytes()
}
}
A.func1()
A.PATH
枚举Enum
enum class A{
EAST,
}
A.EAST
也可以带参数
range
用in检查是否在范围之内
!in
when(a){
"a"->""
else{
}
}
null
除非另有指定,否则不能为null值
?
安全调用操作符 a?.cappitalize()
上面是调用一次时的用法,如果要对这个对象进行多个操作呢?
a?.let{用it代替该变量}
!!又称感叹号操作符,非空断言操作符
a!!.capitalize() // 当变量为空时会执行函数,但也会抛出NPE
也可以使用if a == null
?:代表如果左面的值为null,就使用右面的值 。空合并操作符
异常
try catch
自定义异常,继承
先决条件函数
kotlin提供了一些库函数,叫内置函数,可以抛出带自定义信息的异常,这些便利函数又叫做先决条件函数,你可以用它定义先决条件,条件满足 目标代码才能执行
checkNotNull
require 如果参数为false,抛异常
requireNotNull null抛异常
error null抛异常并输出错误消息
assert 如果false抛异常
checkNotNull(a,"异常信息")
list
mutableList
+=
listOf
removeIf
// 遍历
for (a in list)
list.forEach
forEachIndexed遍历时要获取索引
解构
val (a,b,c)=list
set
setOf
set.elementAt
mutableSetOf
+=
listof().toSet().toList()
listOf().distinct()
数组
IntArray
// 创建
intArrayOf
// 对象数组
ArrayOf
Map
to看上去像关键字,但是是省略了点号和参数的特殊函数,to函数
键 to 值
Pair
mapof("a" to 1)
mapOf(pair("a",10))
getValue
getOrElse(){}//执行
getorDefault(,)//默认值
//
map.forEach{$it.key $it.value}
map.forEach
// mutableMapOf
+="A" to 10
put
getOrPut不存在就添加,否则返回已有键的值