Kotlin(二)之运算符与表达式

文章目录

  • 运算符与表达式
  • 区间运算符
  • 运算符重载
  • 流程控制
  • 标签

运算符与表达式

  1. kotlin不支持java的三目运算符,使用if表达式代替三目运算符。

  2. kotlin的运算符都是以方法形式来实现的,这些运算符都具有特定的符号(如+、*)和固定的优先级。各种运算符对应的方法名都是固定的,我们只要为某类型提供特定名称的方法,成员方法或者扩展方法即可。Kotlin的所有运算符的功能都是广义的,不仅用于数值型、字符串,而且也可作用于任意自定义的Kotlin类。 Kotlin 中的&&、||、?:、===、!==是不能被重载的

  3. 单目前缀

        /**
         * 单目前缀运算符
         * 运算符   对应的方法
         * +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}")
    
  4. 自增和自减

        /****
         * 自加和自减运算符
         *
         * 运算符   对应的方法
         * a++     a.inc()
         * a--     a.dec()
         */
        //var a = 20,输出:20
        println("a:${a++}")
        //输出:22
        println("a:${++a}")
    
  5. 双目算术运算符,

        /***
         * 双目运算符
         * 运算符      对应的方法
         * 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是没问题的
          
    
  6. 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)
    
  7. 索引访问运算符

        /**
         * 索引访问运算符
         * 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])
    
  8. 调用运算符

        /**
         * 调用运算符
         * 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"))
    
  9. 广义赋值运算符

        /**
         * 广义赋值运算符
         * 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
         */
    
  10. 相等与不等运算符

        /**
         * 相等与不相等运算符
         * 运算符     对应的方法
         * 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
    
  11. 比较运算符

    		/**
         * 比较运算符
         * 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
    
  12. is运算符,类似java中的instanceof,但是instanceof判断之后还需要强制转换,而is运算符不需要显示自动转换

    if(a is String){
      println(a.length)
    }
    
  13. 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
    

区间运算符

  1. 区间运算符

    • 闭区间: a … b 用于定义a~b(包括边界)的所有值的区间。对于闭区间,a不能大于b
    • 开区间:半开区间 a until b [a,b) ,从a~b(前闭后开)的所有值的区间,遍历数组和列表方便(因为索引值从0开始到长度-1)
    • 反向区间:a downTo b, 表示区间从大到小(downTo其实是一个infix函数)。b不能大于a
    • 通过step运算符(infix函数)可以显式指定区间的步长
  2. 案例

    	  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)
        }
    

运算符重载

  1. 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)
    }
    

流程控制

  1. 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)
    
  2. when

    • 不在需要使用case关键字

    • case值后的冒号改为使用箭头(->)

    • default改为更有意义、更明确的else

    • when 可以匹配多个值

    • when 分支后的值不要求是常量,可以是任意表达式

    • when 分支对条件表达式的类型没有任何要求(只要条件表达式与某个分支的值通过==比较返回true)

    • when分支也可以作为表达式

    • when分支可以处理范围

  3. 案例

    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)
    
  4. 使用when实现阶乘函数

    fun fact(n: Int): Int {
        return when (n) {
            0, 1 -> 1
            else -> n * fact(n - 1)
        }
    }
    
  5. 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
                }
            }
        }
    
  6. 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
                }
            }
        }
    

标签

  1. 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
    

你可能感兴趣的:(#,Kotlin)