运算符
运算符 | 对应方法 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
a++ | a.inc() |
a-- | a.dec() |
a+b | a.plus(b) |
a-b | a.minus(b) |
a*b | a.times(b) |
a/b | a.div(b) |
a%b | a.rem(b) |
a..b 闭区间 | a.rangeTo(b) 闭区间 |
a in b | a.contains(b) |
a !in b | !b.contains(a) |
a[i] | a.get(i) |
a[i]=b | a.set(i,b) |
a+=b | a.plusAssign(b) |
a-=b | a.minusAssign(b) |
a*=b | a.timesAssign(b) |
a/=b | a.divAssign(b) |
a%=b | a.remAssign(b) |
a==b | a?.equals(b)?:(b===null) |
a!=b | !(a?.equals(b)?:(b===null)) |
a>b | a.compareTo(b)>0 |
a<b | a.compareTo(b)<0 |
a>=b | a.compareTo(b)>=0 |
a<=b | a.compareTo(b)<=0 |
注意1:使用a++和++a和Java中是一致的,再使用对应方法时不太相同,使用时注意,优先使用++
注意2:可以使用in 来判断一个字符串是否包含另一个字符串
**注意3:kotlin中的==相当于是空安全的equals,所以kotlin中引用比较使用===和!==是和java中==和!=是等效的
注意4:在java中只要实现了Comparable接口,就可以通过kotlin中的>,<进行比较,例如String,Date
位运算符(只能对Int和Long起作用)
- and 按位与
- or 按位或
- inv 按位非
- xor 按位异或
- shl 左移运算符
- shr 右移运算符
- ushr 无符号右移运算符
区间运算符
- a until b半开区间
- a downTo b反向闭区间
- a..b 正向闭区间
- step 步长
运算符重载
语法:
1 在对应类中(往往是可以直接修改源码) operator fun 函数名称([参数]):返回值{}
2 不能直接修改源码的时候,使用扩展方法的方式 operator fun 类名.函数名([参数]):返回值{}
流程控制
if... else ...
注意:在使 if else 语句时,一定要先处理包含范围史小的情况。 在使 if se 语句时,一定要先处理包含范围史小的情况。
for..in.. 注意:for...in...中相当于一个用val声明的常量,所以不能从新进行赋值
忽略外层某次循环的语法
outer@ for (i in 0 until 5){
for(j in 0 until 3){
if(j==1){
continue@outer
}
}
}
return
需要注意的是,无论在多少层循环的内部,一旦遇到return,就会直接终止方法或者函数的执行
数组和集合
-
indicies 获取数组索引区间来代替 0 until array.size这种方式来代。
-
find和findLast: 注意:这个其实是调用的firstOrNull和lastOrNull,查找的从前往后第一个和从后往前一个符合条件的元素
-
setOf 和 mutableSetOf返回的是LinkedHashSet ,hashSet返回HashSet是无序的,sortedSet 返回TreeSet从小到大排序,这个是java三种Set的特性决定的。
-
Set 中 intersect/union 是取两个Set的交集和并集
-
mapOf和mutableMapOf返回的是LinkedHashMap,hashMap返回的HashMap是不维护顺序的,linkedHashMap返回的LinkedHashMap按照添加顺序排列,sortedMapOf返回的TreeMap是按照key从小到大排列
函数和Lambda表达式
- 尾递归函数:关键字tailrec修饰 tailrec fun factRec(n: Int, total : Int= 1): Int =
if (n == 1) total else factRec(n - 1 , total * n)
-
高阶函数 双冒号::可以将函数的引用赋给变量
-
局部函数和Lambda 注意点:函数的最后一个表达式自动被当做Lambda表达式的返回值,无须使return关键字 Lambda表达式无法返回指定类型
-
匿名函数和Lambda表达式return
fun main() {
val data = arrayOf(1, 2, 3, 4, 5, 6)
/**
* Lambda中直接使用return会导致直接返回到Lambda所在的函数中,此例子中是直接返回main函数
*/
data.forEach {
println(it)
return
}
/**
* Lambda可以使用return@forEach返回Lambda表达式
*/
data.forEach {
println(it)
return@forEach
}
/**
* Lambda可在之前加上 Lambda名字@ 来给Lambda命名
*/
data.forEach repeat@{
println(it)
return@repeat
}
data.forEach(
fun(i) {
println(i)
//匿名函数中的 return 用于返回该函数本身
return
}
)
}
面向对象
internal 修饰符表示包内可见
中缀表示法
- infix 修饰函数,并且函数只有一个参数
fun main() {
val w1 = Weight(2.2)
val w2 = Weight(3.0)
val w3 = w1 add w2
println(w3.weight)
}
data class Weight(var weight: Double = 0.0) {
infix fun add(weight: Weight): Weight {
return Weight(this.weight + weight.weight)
}
}
componentN,解构 和 setter,getter
class Student {
var name: String? = null
set(name) {
field = name?.reversed()
}
get() {
println("调用get()")
return field
}
var age: Int = 0
operator fun component1(): String? {
return name
}
operator fun component2(): Int {
return age
}
}
main函数调用
val (name, age) = student
println(name)
println(age)
幕后字段
setter和getter中需要使用幕后字段field对属性进行操作
幕后属性
// 这种写法 _age为幕后属性,这样写很复杂,一般不需要这么写
private var _age: Int = age
var age: Int
private set(value) {}
get() = _age
lateinit
- 可变属性
- 不能有自定义setter,getter
- 必须是非空的
- 不能是原生类型(java的8种基本类型)
- 访问之前需要赋值
内联属性
在 getter, setter,属性之前使用inline修饰,表示调用setter和getter会内联化
import
import ... as ... 导包指定别名
java 默认访问控制符:
default class 类名
kotlin 默认访问控制符
public final class 类名
kotlin 取消了java的default(包访问权限),引入了internal访问控制符(模块访问权限) Kotlin取消了protected 的包访问权限
kotlin open 属性重写如果不修改访问权限,会保持重写之前的访问权限
深入构造器
主次构造器都有的情况下 次构造器需要委托init初始化块
语法:
constructor(构造参数列表):this(构造参数列表)
重写父类属性
注意点:重写的属性的修饰符权限要大于等于父类属性的修饰符权限, public >private, var>val
class WashingMachine : Machine() {
override var name: String = "子类属性"
}
open class Machine {
open val name: String = "父类属性"
}
强制重写
当继承了两个类,接口,抽象类中有同名方法,则在子类中必须重写这个重名方法,并且可以通过super<类名>.方法名()选择性的去确定要调用哪些类中的父类
as
- as 类型强转,类型不匹配引发异常
- as?类型不匹配会返回null
内部类和嵌套类
Kotlin中的嵌套类相当于java中的静态内部类,Kotlin中的内部类相当于java中的非静态内部类。
扩展
扩展函数
fun 类.方法名():返回值{}
扩展属性
var 类名.属性名
set(value){
}
get(){}
注意点:
- 扩展属性只能对已有属性进行计算,无法真正的添加随意的属性,因为扩展属性没有field字段
- 需要提供setter和getter
- 不能设置初始值
为类扩展匿名函数(Jectpack 中大量使用了这种方式)
val plusOne=fun Int.():Int{
return this+1
}
val b= a.plusOne()
println(b)
Jectpack Compose 伪代码
class Column(alignment: Int, lambda: Column.() -> Unit)
class Text(text: String)
class Image(img: String)
Column(alignment = 1) {
Text(text = "")
Image(img = "")
}
final 和 open
与java不同的是,kotlin 局部变量不能使用final和open进行修饰
孔int'l孔天林
密封类
异常
Kotlin中异常处理基本与java一致 注意点:在包含多个catch块的时候,应该先catch小异常,再catch大异常,跟if...else... 条件判断一致,先判断小条件,再判断大范围
try {
// 1 / 0 ArithmeticException
// "2-".toInt() NumberFormatException
// println((null as String?)!!.length) NullPointerException
} catch (e: ArithmeticException) {
e.printStackTrace()
} catch (e: NumberFormatException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
} finally {
print("finally 结束")
}
}
自定义异常
class AmountLowException(
message: String? = null, cause: Throwable? = null
) : Exception(message, cause)
@Test
fun throwException() {
fun pay(amount: Double) {
if (amount < 100) {
throw AmountLowException(message = "金额少于100,无法进行充值")
}
print("充值成功")
}
pay(90.0)
}