Kotlin快速入门(二)——运算符和表达式

运算符和表达式

Kotlin基本支持Java的全部运算符(可能有些种子语法上存在差异),Kotlin不支持三目运算符。

1. 与Java相同的运算符

Kotlin的运算符都是以方法形式实现的,这些运算符都具有特定的符号和固定的优先级。

  1. 单目前缀运算符

    运算符 对应的方法
    +a a.unaryPlus()
    -a a.unaryMinus()
    !a a.not
    fun main(args: Array<String>) {
    
        val a = 20
        val b = -a
        val c = a.unaryMinus()
        println("b: $b, c: $c") // b: -20, c: -20
    
        val flag = true
        val f1 = !flag
        val f2 = flag.not()
        println("f1: $f1, f2: $f2") // f1: false, f2: false
    }
    

    如果在API中发现某个类有unaryPlus()unaryMinus()not()方法,那就说明可对该类的实例使用单目前缀运算符+-!进行运算。

  2. 自加和自减运算符

    运算符 对应的方法
    a++ a.inc()
    a-- a.dec()

    如果在API中发现某个类有inc()dec()方法,那就说明可对该类的实例使用++--进行运算。

  3. 双目算术运算符

    运算符 对应的方法
    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)

    如果在API中发现某个类有一个带参数的plus()minus()times()div()rem()rangeTo()方法,那就说明可对该类的实例使用以上双目算术运算符。

  4. in和!in运算符

    运算符 对应的方法
    a in b b.contains(a)
    a !in b !b.contains(a)
    fun main(args: Array<String>) {
    
        val str = "JamFF"
        println(str.contains("java"))
        println("java" in str)
    
        val arr = arrayOf(8, 32, 94, 53, 10)
        println(arr.contains(53))
        println(53 in arr)
    }
    

    如果在API中发现某个类有一个带参数contains()方法,那就说明可对该类的实例使用in!in运算符。

  5. 索引访问运算符

    运算符 对应的方法
    a[i] a.get(i)
    a[i, j] a.get(i, j)
    a[i_l, ..., i_n] a.get(i_l, ..., i_n)
    a[i]=b a.set(i ,b)
    a[i, j]=b a.set(i, j, b)
    a[i_l,...,i_n]=b a.set(i_l ,..., i_n)
  6. 调用运算符

    运算符 对应的方法
    a() a.invoke()
    a(b) a.invoke(b)
    a(b1, b2) a.invoke(b1, b2)
    a(b1, b2, b3, ...) a.invoke(b1, b2, b3, ...)
    fun main(args: Array<String>) {
    
        val s = "java.lang.String"
        val mtd = Class.forName(s).getMethod("length")
        // 使用传统方法,使用Method对象的invoke方法
        println(mtd.invoke("java")) // 输出4
        // 使用调用运算符
        println(mtd("java")) // 输出4
    }
    
  7. 广义赋值运算符

    运算符 对应的方法
    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)
  8. 相等于不等运算符

    运算符 对应的方法
    a == b a?.equals(b):(b===null)
    a != b !(a?.equals(b)?:(b===null))

    Kotlin中==equals本质是一样的,只不过==避免了空指针;而Java中比较对象的==!=在Kotlin中由===!==代替。

  9. 比较运算符

    运算符 对应的方法
    a > b a.compareTo(b) > 0
    a < b a.compareTo(b) < 0
    a >= b a.compareTo(b) >= 0
    a <= b a.compareTo(b) <= 0

    如果在API中发现某个类实现了Comparable方法,那就该类的实例即可使用比较运算符来比较大小。

2. 位运算符

Kotlin支持的位运算符同样有7个,但是并不是特殊字符形式,而是以infix函数的形式给出的,因此只能用函数名执行这些位运算符。

  • and(bits):按位与。
  • or(bits):按位或。
  • inv(bits):按位非。
  • xor(bits):按位异或。
  • shl(bits):左移运算符。
  • shr(bits):右移运算符。
  • ushr(bits):无符号右移运算符。

Kotlin的位运算符只能对IntLong两种数据类型起作用。

3. 区间运算符

  1. 闭区间运算符
    a..b定义一个从a到b(包含a和b)的所有值的区间。

    fun main(args: Array<String>) {
    
        val range = 2..6
        for (num in range) {
            print("$num ") // 输出2 3 4 5 6
        }
    }
    
  2. 半开区间运算符
    a until b定义一个从a到b(包含a,不包含b)的所有值的区间。
    利用半开区间便利数组的列表时非常方便。

    fun main(args: Array<String>) {
    
        val books = arrayOf("Swift", "Kotlin", "C", "C++")
        for (index in 0 until books.size) {
            println("第${index + 1}中语言是:${books[index]}")
        }
    }
    
  3. 反向区间
    如果希望区间从大到小,可以使用downTo运算符(其实是一个infix函数),该运算符同样是一个闭区间。

    fun main(args: Array<String>) {
    
        val range = 6 downTo 2
        for (num in range) {
            print("$num ") // 输出6 5 4 3 2
        }
    }
    
  4. 区间步长
    前面区间的默认步长都是1,可通过step运算符(其实是一个infix函数)指定区间步长。

    fun main(args: Array<String>) {
    
        for (num in 7 downTo 1 step 2) {
            print("$num ") // 输出7 5 3 1 
        }
    }
    

4. 运算符重载

重载运算符的方法需要运用operator修饰符进行标记。

  1. 重载单目前缀运算符

    data class Data(val x: Int, val y: Int) {
        // 为Data类定义一个unaryMinus()方法
        operator fun unaryMinus(): Data {
            return Data(-x, -y)
        }
    }
    
    // 以扩展方法的形式为Data类定义unaryPlus()方法
    operator fun Data.unaryPlus(): Data {
        return Data(-x, -y)
    }
    
    fun main(args: Array<String>) {
    
        val d = Data(4, 10)
        println(-d)
        println(+d)
    }
    
  2. 重载自加和自减运算符

    data class Data(val x: Int, val y: Int) {
        // 为Data类定义一个inc()方法
        operator fun inc(): Data {
            return Data(x + 1, y + 1)
        }
    }
    
    // 以扩展方法的形式为Data类定义dec()方法
    operator fun Data.dec(): Data {
        return Data(x - 1, y - 1)
    }
    
    fun main(args: Array<String>) {
    
        var d = Data(4, 10)
        println(d++) // 输出Data(x=4, y=10)
        println(d) // 输出Data(x=5, y=11)
        var dd = Data(9, 20)
        println(--dd) // 输出Data(x=8, y=19)
        println(dd) // 输出Data(x=8, y=19)
    }
    
  3. 重载双目算术运算符

    data class Point(val x: Int, val y: Int) {
        // 为Point类定义一个minus()方法
        operator fun minus(target: Point): Double {
            return Math.hypot((this.x - target.x).toDouble()
                    , (this.y - target.y).toDouble())
        }
    }
    
    // 以扩展方法的形式为Point类定义dec()方法
    operator fun Point.times(target: Point): Int {
        return Math.abs(this.x - target.x) *
                Math.abs(this.y - target.y)
    }
    
    fun main(args: Array<String>) {
    
        val p1 = Point(0, 0)
        val p2 = Point(3, 4)
        println("p1与p2的距离为:${p1 - p2}") // 输出5
        println("p1与p2围成的矩形面积为:${p1 * p2}") // 输出12
    }
    

重点

  • in!in运算符
  • =====运算符
  • 位运算符
  • 区间运算符
  • 运算符重载
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 本文是在学习和使用kotlin时的一些总结与体会,一些代码示例来自于网络或Kotlin官方文档,持续更新... 对...
    竹尘居士阅读 3,265评论 0 8
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,320评论 0 2
  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,415评论 1 24
  • 最近公司计划用上新的技术 React Native,所以就开始学习研究。 首先搭建开发环境 准备工作 安装 Hom...
    wanqijian阅读 234评论 0 0
  • 昔日同欢忘忧伤,云湿门窗,雨湿门窗; 而今独自对浣江,风在回廊,月在回廊! 齐帆齐写作课第六期学员第二十四篇
    花氏一族阅读 357评论 0 1