常量和只读变量一旦初始化就不能再被修改。在kotlin中,声明常量是在标识符的前面加上val或const val 关键字。
1. val 声明的是运行时变量,在运行时进行初始化
2.const val 声明的是编译时常量,在编译时初始化
val 相当于 final
const val 相当于 public static final
例子:
var n:Int = 10 n=null 编译错误
var n:Int?=10 n=null 可以
Kotlin 安全运算符
1.安全调用运算符?.
2.安全转换运算符 as?.
3.Elvis 运算符?:
也叫 空值合并运算符 例子:
var a=divide(100,0)
int x=a?:0
结果x=0
意思就是 假如a是空值,则让x=0 相当于给他一个默认值,空的就赋值0,避免了null 报错
4.非空断言 !!
val s1="Hello"
val s2="HELLO"
s1.equals(s2,ignoreCase = true)//忽略大小写比较内容是否相等 结果为true
除了equals 之外,还有compareTo ,这个比较的是顺序,返回的是数字,
如果俩个字符串相等结果为0,前面的小就返回负数,大就返回正数
冒号: 用于变量或者常量类型声明,以及声明继承父类和实现接口
小括号():起到改变表达式运算顺序的作用,他的优先级更高
中括号【】:索引访问运算符号
等号:赋值
可空符?标识一个可空类型
安全调用运算符?. 调用非空类型的函数或者属性
Elvis ?: 空值合并运算符
非空断言 !! 就是一定不会是空值
双冒号:: 引用类,属性或函数
区间.. :表示一个范围区间
箭头-> 用来声明lambda 表达式
展开运算符*将数组传递给可变参数时使用
if else
when(){
x->{
}
}
do{
}while()
for( a int 0..9){
}
for(a int 0..list.size){}
for(item in list){}
//获取数组索引
for(i in list.indices){}
for(x in 0..5) //定义区间包含0和5
for(x int 0 until 5) //定义半开区间包含0,不包含5
例子
var testScore=80 //设置一个测试分数var grade=when(testScore){in 90..100->"优秀"in 80 until 90->"良"in 60 until 80->"中"in 0 until 60->"差"else->"无"}if(testScore !in 60..100){println("不及格")}val strList= arrayOf("刘备","关羽","关羽")var name="赵云"if(name !in strList){println(name+"没结义")}
fun 函数名(参数列表) : 返回值类型{
函数体
return 返回值
}
xxx(100,100)//没有采用
xxx(width=100,height=100)//采用命名函数
xxx(100,height=100)//采用
这个操作,之前的java使用参数提示的,命名函数可能有其他操作吧
这里可以和扩展运算符*结合
fun nimingTEST(a:Int,b:Int):String{val xxx=if(a==b)fun (x1 : Int, x2:Int):String{return (x1+x2).toString() }elsefun (x1 : Int, x2:Int):String{return (x1-x2).toString() }return xxx(a,b)}
感觉这个不如一条一条列出来清晰
lateinit 字面意思延迟初始化,用的时候才会实例化,实例化是占内存,这个可以避免内存消耗吧
lateinit 关键字放在var之前,不能是可空类型
这里做了一个点击查看的操作,是可以监听到的,
//基本数据类型扩展fun Double.interestBy(interestRate: Double): Double {return this * interestRate}//自定义账户类class Account {var amount: Double = 0.0 //账户金额var owner: String = "" //账户名}//账户类函数扩展fun Account.interestBy(interestRate: Double): Double {return this.amount * interestRate}
Double 类型可以引用
看起来很方便
这个看起来只能在当前类中使用
肯定可以写全局的
写一个文件,注意是文件不是类
这样直接在其他地方可以用了,需要注意是在同一个包里
默认是自带无参数构造
创建一个类,区分了是数据类还是工具类还是其他类
数据类关键词data
添加一个data关键字后变成了数据类,底层数据类
底层的三个方法
hash() toString equals 另外增加了一个copy的方法
data 修饰的类 参数有要求,必须要有var/val修饰
打印出来是2,也就是 修改了其中一个值其他都是之前的
无法访问外部类成员变量
加一个内部类关键字就可以了
Object关键字
接口回调
Kotlin 没有 java中的Static 所以
伴生类不能访问外部类的成员属性啥的,这个交互起来,还是以外部类为主
关键字open,Kotlin 默认是 final修饰的类和属性只有加上open才能被继承
都一样,哪个代码少用哪个
is 相当于 instanceof as 相当于强类型转换
费劲巴拉的你直接宽*高不就得了。
使用案例2
简便了为啥我感觉花里胡哨的没有java通俗易懂
简化之后Int直接省略了
省略写法
没啥意思啊~
return@foreach可以跳出本次循环,return 和 break 会跳出整个循环
这种写法就可以用continue
这个有点绕
关键字inline
let的特点 1 最后一行是赋值
let特点2非空检查
在koltin中防止引用null对象,所有的对象都可以调用let方法,为空时不执行,不为空时执行
a是自己取的名字,可以使用默认的it
let特点3 直接读取调用链结果
例子
这里拿到的是他们的长度,但是我想要字符串本身
直接拿到数据
map是转换的意思
和run类似,但是他没有返回值
假设要做一个比较的方法
这里只能比较int 参数
在方法名之前加上
如果是多类型的
假如只想比较数字方向的类型,可以大概给个Number,他的子类有Int Double
也可以写成
Comparable包括了很多可以比较的类型,前后的参数一定要一个类型的
假如参数是空的,我们需要防止
可空
不可空
filter
过滤
map
转换
reduce
聚合
// n个元素val intArray = IntArray(2) {it + 1}val reduce = intArray.reduce { acc, i ->acc * i}println(reduce)
从1开始到n的阶乘
结果是从0到999
在执行阻塞任务时.会将这种任务放到子线程中,执行完成再回调(callback)主线程,更新UI等操作,这就是异步编程。协程底层库也是异步处理阻塞任务,但是这些复杂的操作被底层库封装起来。协程代码的程序流是顺序的,不再需要一堆的回调函数,就像同步代码一样,也便于理解,调试和开发
线程是抢占式的,线程调度是操作系统级的,而协程是协作式的,协程调度是用户级的,协程是用户空间线程,与操作系统无关,所以需要用户自己去做调度
launch 函数的返回值是一个Job对象,Job是协程要执行的任务,可以将Job对象看做协程本身,所有对协程的操作都是通过Job对象完成的,协程的状态和生命周期都是通过Job反应出来的
Job对象的常用属性和函数
isActive 判断Job是否处于活动状态
isCompleted判断Job是否处于完成状态
isCanceled判断Job是否处于取消状态
start 开始Job
cancel取消Job
join 当前协程处于等待状态,知道Job完成,join是一个挂起函数,只能在协程体中或其他的挂起函数中调用
launch 和 runBlock 是相反的,runBlock 会阻塞线程
从这里可以看出通过.launch开启一个协程会被先挂起,同级别的代码会先运行,
suspend就是让协程该走就走,执行完在回来,给主线程或者说同级别的代码块更好的运行
这里的运行顺序换成runBlock
和上面相反程序会等runblock 执行完再执行下面
由于这种操作有可能阻塞主线程,所以很少有
简单实用的场景
butStart.setOnClickListener(View.OnClickListener {
val coroutineScope = CoroutineScope(Dispatchers.Main)
coroutineScope.launch {
withContext(Dispatchers.IO) {
Thread.sleep(5000)
a = 20
}
text.text = ""+a
}
})
可以通过withContext 把它切换到子线程,
以后用它替换java的AsycnTask吧,至于其他方法太烦了