kotlin不支持java的三目运算符,使用if表达式代替三目运算符。
kotlin的运算符都是以方法形式来实现的,这些运算符都具有特定的符号(如+、*)和固定的优先级。各种运算符对应的方法名都是固定的,我们只要为某类型提供特定名称的方法,成员方法或者扩展方法即可。Kotlin的所有运算符的功能都是广义的,不仅用于数值型、字符串,而且也可作用于任意自定义的Kotlin类。 Kotlin 中的&&、||、?:、===、!==是不能被重载的
单目前缀
/**
* 单目前缀运算符
* 运算符 对应的方法
* +a a.unaryPlus()
* -a a.unaryMinus()
* !a a.not()
*/
var a = 20;
val b = -a
val c = a.unaryMinus()
//输出:b:-20,c:-20
println("b:${b},c:${c}")
val d = +a
val e = a.unaryPlus()
//输出:b:20,c:20
println("b:${d},c:${e}")
var flag = true
val f = !flag
val g = flag.not()
//f:false,g:false
println("f:${f},g:${g}")
自增和自减
/****
* 自加和自减运算符
*
* 运算符 对应的方法
* a++ a.inc()
* a-- a.dec()
*/
//var a = 20,输出:20
println("a:${a++}")
//输出:22
println("a:${++a}")
双目算术运算符,
/***
* 双目运算符
* 运算符 对应的方法
* 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)
*/
//输出:11
println(5 + 6)
//输出:11
println(5.plus(6))
//输出:30
println(5 * 6)
//输出:30
println(5.times(6))
//在kotlin里1+""是会运行报错的,因为Int没有对+重载 只能1.toString()+""
//在kotlin里""+1是没问题的
in与!in
/**
* a in b b.contains(a)
* a !in b !b.contains(a)
*/
var str = "jannal"
println(str.contains("jan"))
println("jan" in str)
索引访问运算符
/**
* 索引访问运算符
* a[i] a.get(i)
* a[i,j] a.get(i,j)
* a[i1,...,in] a.get(i1,...,in)
* a[i] = b a.set(i,b)
* a[i,j] = b a.set(i,j,b)
* a[i1,...,in]=b a.set(i1,...,in,b)
* 只要提供get和set的类都可以使用索引运算符,比如String和ArrayList
*/
var list = ArrayList<String>()
list.add("jannal")
list.add("tom")
list.add("jack")
//tom
println(list[1])
list[1] = "tomcat"
//tomcat
println(list[1])
调用运算符
/**
* 调用运算符
* a() a.invoke()
* a(b) a.invoke(b)
* a(b1,b2) a.invoke(b1,b2)
* a(b1,b2,b3...) a.invoke(b1,b2,b3)
*
*/
val s = "java.lang.String"
val method = Class.forName(s).getMethod("length");
//输出:4
println(method.invoke("java"))
//输出:4
println(method("java"))
广义赋值运算符
/**
* 广义赋值运算符
* a+=b a.plusAssign(b)
* a-=b a.minusAssign(b)
* a*=b a.timesAssign(b)
* a/=b a.divAssign(b)
* a%=b a.remsAssign(b)
*
* 编译器会先判断plusAssign()是否存在
* - 如果存在,并且plus()也存在,报告错误。
* - 如果存在,并且plus()不存在,再次判断plusAssign是否有返回值,有则报错'
* - 如果能通过前两步检查,则a+=b将转换为a=a+b
*/
相等与不等运算符
/**
* 相等与不相等运算符
* 运算符 对应的方法
* a==b a?.equals(b)?:(b===null)
* a!=b !(a?.equals(b)?:(b===null))
* ==与equals等价,只不过==是空指针安全的
* java中的==和!= 在kotlin中使用===和!==代替,===和!==不能重载
*/
var s1 = java.lang.String("java")
var s2 = java.lang.String("java")
println(s1 == s2)//true
println(s1.equals(s2))//true
println(s1 === s2)//false
println(s1 !== s2)//true
var s3 = "java"
var s4 = "java"
println(s3 == s4)//true
println(s3 === s4)//true
比较运算符
/**
* 比较运算符
* a>b a.compareTo(b)>0
* a=b a.compareTo(b)>=0
* a<=b a.compareTo(b)<=0
* 所有支持使用compareTo方法比较大小的对象(实现Compareable接口)都可以使用比较运算符
*/
var s5 = "java"
var s6 = "kotlin"
println(s5 > s6)//false
println(s5.compareTo(s6) > 0)//false
is运算符,类似java中的instanceof,但是instanceof判断之后还需要强制转换,而is运算符不需要显示自动转换
if(a is String){
println(a.length)
}
as运算符用于执行引用类型的显示类型转换, 如果要转换的类型与指定的类型兼容, 转换就会成功进行; 如果类型不兼容,就会抛出ClassCastException异常。可以使用 as?运算符,如果转换失败返回 null
open class Parent
class Child : Parent()
val parent = Parent()
val child = Child()
//子类型可以转换为父类型
println(child as Parent)
//父类型不能强制转换为子类型
println(parent as? Child) //null
val parent1: Parent = child
println(parent1 as Child) //如果实际类型本身就是子类型,是可以强转成功的
println(parent as Child) //如果实际类型本身就是不是子类型,会抛出异常java.lang.ClassCastException
区间运算符
infix
函数)。b不能大于ainfix
函数)可以显式指定区间的步长案例
var rangeNum = 2..6
for (num in rangeNum) {
println("${num} * 5 = ${num * 5}")
}
var users = arrayOf("jannal", "tom", "jack")
for (index in 0 until users.size) {
println("第${index + 1}个人的名字是:${users[index]}")
}
//从6逆序降到2,默认步长是1
var rangeNum1 = 6 downTo 2
for (num in rangeNum1) {
//65432
print(num)
}
println()
//从6降序到2,默认步长是2
var rangeNum2 = 6 downTo 2 step 2
for (num in rangeNum2) {
//642
print(num)
}
Kotlin的运算符都是靠特定名称的方法支撑的。因此只要重载这些名称的方法,就可以为任意类添加这些运算符。
/**
* 重载单目运算符
* 1. 只要为任意类定义名为unaryPlus()、unaryMinus()、not()
* 2. 以operator修饰方法
*
* 重载其他运算符道理相同
*/
data class Data(val x: Int, val y: Int) {
operator fun unaryMinus(): Data {
return Data(-x, -y)
}
}
//以扩展方法的形式为Data类定义not()方法
operator fun Data.not(): Data {
return Data(-x, -y)
}
fun main(args: Array<String>) {
val d = Data(4, 10)
println(-d)
println(!d)
}
kotlin提供两种分支 if和when,when取代switch,if是一个表达式,即返回一个值,if分支代码块最后的表达式作为该块的值,如果if作为表达式必须有else分支。kotlin中没有三元运算符,可以通过if表达式来实现
//if作为表达式
var age = 20
var str = if (age > 20) "age大于20" else if (age < 20) "age小于20" else "age等于20"
//age等于20
println(str)
//实现三元运算符的逻辑
var result = if(true) 1 else 0
println(result)
when
不在需要使用case关键字
case值后的冒号改为使用箭头(->)
default改为更有意义、更明确的else
when 可以匹配多个值
when 分支后的值不要求是常量,可以是任意表达式
when 分支对条件表达式的类型没有任何要求(只要条件表达式与某个分支的值通过==比较返回true)
when分支也可以作为表达式
when分支可以处理范围
案例
fun main(args: Array<String>) {
//if作为表达式
var age = 20
//age等于20
var str = if (age > 20) "age大于20" else if (age < 20) "age小于20" else "age等于20"
println(str)
var score = 'B'
when (score) {
'A' -> println("优秀")
'B' -> println("良好")
'C' -> println("中")
'D' -> println("及格")
'E', 'F' -> {
println("差")
}
else -> println("不及格")
}
}
//when与in、!in结合,是否在指定区间或者集合中
var num: Int = Random().nextInt(100)
var str1 = when(num){
in 1..60 -> "1~60"
in 61..70 -> "61~70"
in 71..80 -> "71~80"
in 81..90 -> "81~90"
else -> "91~100"
}
println(num)
println(str1)
//在 Kotlin 1.3 中,可以将when表达式主语捕获到变量中,这样变量的作用域就可以限定在when中
when (val num2: Int = Random().nextInt(100)) {
in 1..60 -> println("1~60")
in 61..70 -> println("61~70")
in 71..80 -> println("71~80")
in 81..90 -> println("81~90")
else -> println("91~100")
}
var a: String? = "1"
val mode = when {
a == "1" -> 1
a == "2" -> 2
else -> 0
}
//1
println(mode)
使用when实现阶乘函数
fun fact(n: Int): Int {
return when (n) {
0, 1 -> 1
else -> n * fact(n - 1)
}
}
break中断外层循环,使用一个自定义标签outer@
//使用break中断外层循环
outer@ for (i in 0 until 5) {
var j = 0
while (j < 3) {
println("i:${i},j:${j++}")
if (j == 2) {
break@outer
}
}
}
continue跳过外层循环
//使用continue跳过外层循环
outer@ for (i in 0 until 5) {
var j = 0
while (j < 3) {
println("i:${i},j:${j++}")
if (j == 2) {
continue@outer
}
}
}
Kotlin中任何表达式都可以使用标签(label)来标记。标签的格式为标识符后跟@符号。比如abc@
都是有效的标签。可以用标签来控制return、break、continue语句的跳转
var array = intArrayOf(1, 2, 3, 4)
//在lambda表达式开头处添加start@,可以理解为
//该标签相当于记录lambda表达式的指令执行入口地址
array.forEach start@{
if (it == 3) {
return@start
}
println(it)
}
//隐式标签
array.forEach {
if (it == 3) {
return@forEach
}
println(it)
}
输出:
1
2
4
1
2
4