kotlin基础语法

每种编程语言都有一定的语法、语义和执行顺序(同步),学习一种新语言也都是从这三者出发,下面我们就只针对kotlin的语法来做简单的介绍。

Kotlin有自己的特性不该被Java的思维所束缚。

  1. 基本语法准则:
    在Kotlin中常量用 val 声明,变量用 var 声明;
    关键字在前面,类型以冒号 :隔开在后面,也可以省略直接赋值;
    类型后带问号 ? 表示可为空类型(默认空类型安全);
    常量 val 延迟加载 by lazy{} ;
    默认是线程安全的,关闭线程安全 lazy(LazyThreadSafetyMode.NONE){} ;
    变量 var 延迟加载 lateinit ;
    内部类和参数默认为public,而在Java中为private
    类默认为不可继承(final),想要可被继承要声明为 open 或 abstract
    取消了static关键字,静态方法和参数统一写在 companion object 块
    internal模块内可见,inner内部类
//常量数组int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
internal var name: String? = null//类型后带问号 ? 表示可为空类型(默认空安全)
internal var age: Int = 0//internal模块内可见,inner内部类
//当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。
open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)

kotlin是空类型安全的,所有变量默认为"not null",必须显式在类型后添加?修饰符才可赋值为null。

var notNullArtist: Artist = null//编译不通过,因为notNullArtist不能为null
var artist: Artist? = null//编译通过
artist.print()//编译不通过,因为artist可能为空
/** Kotlin进行空判断处理,有两种处理方式:
     * 1. 抛出空异常,字段后加 !! 
     * 2. 不做处理直接跳过,字段后加 ?
     */
artist?.print()//编译通过,做了非空判断,只有当artist!=null时才调用print()
artist!!.print()//这种用法只有在确认artist不为null时才能调用,否则抛出空指针异常
val name = artist?.name?:"empty"//当artist为null时可以指定一个默认值
  1. 条件语句
    if...else 正常使用,不过移除了 switch 用更强大的 when 替代,when子式可以是各种返回Boolean的表达式
val x = 7
when (x) {
  in 1..5 -> print("x is in the range")
  in validNumbers -> print("x is valid")
  !in 10..20 -> print("x is outside the range")
  else -> print("none of the above")
}

kotlin尽可能多的使用when

  1. 循环语句
    while 和 do...while 同Java并无区别, for 则有很大改变并多出了几个变种
fun main(args: Array<String>) {
    var list = ArrayList<String>()
    add(list)
    list.forEachIndexed { i, s ->
    print(list[i])
    print(s)
    }
    println()
    //如果没有指定函数的返回值,它就会返回Unit,与Java中的void类似,但是Unit是一个真正的对象。当然也可以指定任何其它的返回类型:
    list.forEachIndexed(object :(Int,String) -> Unit{
    override fun invoke(i: Int, s: String) {
        print(list[i])
        print(s)
    }
})
}
//递增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
   print(list[i])
}
//递增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
   print(list[i])
}
//递减for (int i = list.size(); i >= 0; i--)
for (i in list.size downTo 0) {
    print(list[i])
}
//操作列表内的对象
for (item in list) {
    print(item)
}
//加强版
for((i,item) in list.withIndex()){
    print(list[i])
    print(item)
}
//变种版
list.forEach {
    print(it)
}

list.forEachIndexed { i, s ->
    print(list[i])
    print(s)
}

list.forEachIndexed(object :(Int,String) -> Unit{
    override fun invoke(i: Int, s: String) {
        print(list[i])
        print(s)
    }
})
fun add(list:MutableList<String>) {
        for (i in 0..4) {
            list.add(i.toString() + "")
        }
    }

冒号使用
  在Kotlin中冒号 : 用万能来称呼绝不为过。常量变量的类型声明,函数的返回值,类的继承都需要它

除此之外还有一个特别的地方也需要它,使用Java类的时候。Kotlin最终会还是编译成Java字节码,使用到Java类是必然的,在Kotlin语法如下
val intent = Intent(this, MainActivity::class.java)

指定上下文的@

除了冒号另一个重要符号 @ ,java代码中经常用到内部类和匿名内部类,有时我们不能确定this指代的上下文,Java可以使用XXX.this指代具体上下文,在kotlin中的做法是this@XXX

class User {
    inner class State{
        fun getUser(): User{
            //返回User
            return this@User
        }
        fun getState(): State{
            //返回State
            return this@State
        }
    }
}

kotlin的特色

Java的 getter/setter 方法自动转换成属性,对应到Kotlin属性的调用

public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

对应的kotlin

val user = User()
//赋值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age

class User {
    var name: String? = null
    var age: String? = null
}

有时 getter/setter 方法比较复杂,这就需要自定义 getter/setter 了,实现一个Java中常用的单例,这里只为了展示,单例在Kotlin有更简单的方法实现,只要在 package 级别创建一个 object 即可

class User {
    companion object {//静态方法和参数统一写在 companion object 块
         //volatile不保证原子操作,所以,很容易读到脏数据。在两个或者更多的线程访问的成员变量上使用volatile
        @Volatile var instance: User? = null
            get() {
                if (field == null) {
                    synchronized(User::class.java) {
                        if (field == null)
                            field = User()
                    }
                }
                return field
            }
    }

    var name: String? = null
    var age: String? = null
}

自定义 getter/setter 重点在 field ,跟我们熟悉所Java的 this 指代当前类一样, field 指代当前参数,直接使用参数名 instance 代替不会报错但单例就没效果了

字符串问题

在Java中拼接字符串的代码可读性都很差,在Kotlin字符串拼接变得非常简洁,只需用 $ 后面加上参数名,复杂的参数要加上 {}

 val pair = Pair(1, "one")
 val (num, name) = pair
 println("num = $num, name = $name")

输出num = 1, name = one

Java8新特性lambda的支持

lambda需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。使用功能接口,把接口名、方法名和参数类型省掉不写再加个 -> 罢了。

使用Java开发Android时,处理监听回调是常见的事,kotlin可以直接编写监听回调而不用再通过匿名对象传递onClick方法,这个特性被称为Lambda表达式

view.setOnclickListener({
      Toast.makeText(this, "Hello World!", Toast.LENGTH_LONG).show()
})

扩展函数

可以为任何已经存在的类添加新函数,相比传统工具类,扩展函数更具有可读性。

//为Fragment添加扩展函数
fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_LONG){
      Toast.makeText(getActivity(), message, duration).show()
}

调用时直接调用fragment.toast("Hello World!")或fragment.toast("Hello World!", 2000)

Kotlin中的参数与Java中有些不同。如你所见,我们先写参数的名字再写它的类型。上面调用的第二个参数(length)指定了一个默认值。这意味着你调用的时候可以传入第二个值或者不传,这样可以避免你需要的重载函数。

函数式支持(lambda),函数是一级公民

集合操作

  list转map(associateBy)

  场景:订单列表转换成以 id为key 的订单map

val mainOrders = orderDao!!.queryUserOrder(param)
val orderMap = mainOrders.associateBy { it.id }.toMap()

  map的key或者value转换

  假如一个map的key是String,需要转换成Long;或者map的value是一个对象,要转成另一个对象。按照标准Java写法,可以要new一个新的map,然后循环老的map,在kotlin中,一行代码搞定

val map = mutableMapOf(1 to 1, 2 to 2)
val newMap = map.mapKeys { "key_${it.key}" }.mapValues { "value_${it.value}" }
println(newMap)
//打印结果 {key_1=value_1, key_2=value_2}
val pair = Pair("ss","sg")
 val map = mapOf(pair)
val map1=map.mapKeys { entry -> "${entry.value}!"  }
    for((key,value) in map1){
        println("map1:key=$key")
        println("map1:value=$value")
    }
        val map2 =map.mapKeys { (key, value) -> "$value"  }
    for((key,value) in map2){
        println("map2:key=$key")
        println("map2:value=$value")
    }
        val map3=map.mapValues { entry -> "${entry.value}!" }
    for((key,value) in map3){
        println("map3:key=$key")
        println("map3:value=$value")
    }
        val map4=map.mapValues { (key, value) -> "$value" }
    for((key,value) in map4){
        println("map4:key=$key")
        println("map4:value=$value")
    }
打印结果:
map1:key=sg!
map1:value=sg
map2:key=sg
map2:value=sg
map3:key=ss
map3:value=sg!
map4:key=ss
map4:value=sg

参考文献
  Kotlin for android Developers
  kotlin 脚本练习

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

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,146评论 9 118
  • 一、常量与变量(val,var) 1.什么是常量? 1 .val = value ,值类型;2.类似Java的fi...
    Serenity那年阅读 529评论 0 7
  • 1.函数 (1)Main函数默认是Unit返回类型,可以定义其他返回类型:Int (2)直接声明一个函数,给出返回...
    贾里阅读 490评论 0 0
  • 基本类型 在 Kotlin 中,所有东西都是对象,在这个意义上讲我们可以在任何变量上调用成员函数和属性。 一些类型...
    Whyn阅读 425评论 0 0
  • 青青,是一个即将毕业的求职狗! 一开始,他热血沸腾,信心满满!但四处碰壁!后来,觉得是个工作就行!再后来呢?他的结...
    这个糖不太甜阅读 382评论 0 0