kotlinAndroid开发经验谈Android开发

初识Kotlin<上>

2017-11-16  本文已影响24人  我是李小米

前边就不用过多的介绍了,自从Google选择Kotlin,有一波开发者开始学习了。下边记录一下第一次学习Kotlin的一些笔记。

1、变量及常量的定义

说一个var和val的区别
var是定义一个变量,以后这个值是可以变的
val是定义一个常量,在以后的操作过程中,这个值是不能变的.

    val a: Int = 1  // 立即初始化
    val b = 2   // 推导出Int型
    val d = 2.357   // 小数,默认为doulbe类型
    var c: Int? = null    // 当没有初始化值时必须声明类型

2、元组

这个貌似是个新鲜的东西,之前在java语言里边是没有这个东西的。看一下怎么用。

        /**
         * 元组   三元元组
         */
        var (name, move, number) = kotlin.Triple("小米", "左", 3)
        LogUtils.Loge("${name}向${move}边移动了${number}步")

        /**
         * 二元元组
         */
        var (name1, move2) = Pair("小明", "右")
        LogUtils.Loge("${name1}向${move2}边移动了5步")

        /**
         * 二元元组
         */
        var move3 = Pair("小红", "前")
        LogUtils.Loge("${move3.first}向${move3.second}边移动了10步")

然后看一下控制台的输出的效果:

11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小米向左边移动了3步###
11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小明向右边移动了5步###
11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小红向前边移动了10步###

定义一个三元元组使用Triple关键字,定义一个二元元组使用Pair关键字。如果不想给元组定义多个变量,可以使用第三个写法中的方式,然后在使用元组中的参数的时候,使用"变量名.first" .
嗯嗯,这里大家还可以看到一个骚操作,如果要把字符串和变量拼接起来,是用${变量名}来在字符串中拼接。

3、集合

在Kotlin中集合分为三种形式:
Set: 无序不重复、List:有序可重复,索引从0开始、Map(映射):无序不重复,键值对

3.1先看Set、看代码:
        //定义一个不可变的Set集合
        var mStringSet1: Set<String> = setOf("E", "F", "B", "C", "A", "D", "F", "B")
        //定义一个可以变的Set集合
        var mStringSet2: Set<String> = mutableSetOf("E", "F", "B", "C", "A", "Z")
        //创建一个空的Set集合
        var mStringSet3: Set<String> = emptySet()

        LogUtils.Loge("数量:" + mStringSet1.count())
        LogUtils.Loge("是否为空:" + mStringSet3.isEmpty())
        for (item in mStringSet1) {
            LogUtils.Loge(item + ">>>mStringSet1")
        }
        //是否包含某个元素
        LogUtils.Loge("判断是否包含某个元素:" + mStringSet1.contains("A"))
        //是否包含某个集合
        LogUtils.Loge("判断是否包含某个集合:" + mStringSet1.containsAll(mStringSet2))
        //转换成list
        val toTypedArray = mStringSet1.toTypedArray()
        for (s in toTypedArray) {
            LogUtils.Loge("集合转换成数组:" + s)
        }

        //集合之间的操作
        val intersect = mStringSet1.intersect(mStringSet2)
        LogUtils.Loge("交集:" + intersect)

        val union = mStringSet1.union(mStringSet2)
        LogUtils.Loge("全集:" + union)

        val subtract = mStringSet1.subtract(mStringSet2)
        LogUtils.Loge("差集:" + subtract)

        val minus = mStringSet1.minus(mStringSet2)
        for (minus1 in minus) {
            LogUtils.Loge("补集:" + minus1)
        }

        //转换成ToMutableSet
        val toMutableList = mStringSet2.toMutableList()
        for (s in toMutableList) {
            LogUtils.Loge("toMutableList:" + s)
        }

        //MutableSet:大小可变的集合

        //增加一个
        toMutableList.add("K")
        for (s in toMutableList) {
            LogUtils.Loge("新增加了一个:" + s)
        }

        //增加一堆
        toMutableList.addAll(mStringSet1)
        for (s in toMutableList) {
            LogUtils.Loge("新增加了一堆:" + s)
        }

        //删除第0个
        toMutableList.removeAt(0)
        for (s in toMutableList) {
            LogUtils.Loge("删除第0个:" + s)
        }
        //删除某一个
        toMutableList.remove("K")
        for (s in toMutableList) {
            LogUtils.Loge("删除某一个:" + s)
        }

set集合是不可重复的且无序的集合,但是在上述代码mStringSet1集合中出现了重复的元素,大家可以看一下效果,虽然在初始化的时候,集合中包含重复元素,但是在使用的时候是不会出现重复元素的。看一下控制台输出:

11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: E>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: F>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: B>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: C>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: A>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: D>>>mStringSet1###

然后在set集合中咱们可以求两个set集合交集、差集、并集、补集。具体的操作在上述代码中有体现,大家可以去自行试试效果。
还有一点,在初始话set集合的时候,是一个不可变的集合,在后续操作中不能对集合进行增加、删除元素等操作。如果我们想要去操作集合,就要调用集合的.toMutableList()方法,然后再去对集合进行add()、addAll()、remove()等操作。

3.2 再看List集合:

list集合是一个有序,可重复的集合。
所以在list集合比set集合多了拿到第几个元素的方法,调用 stationsList[index])或者stationsList.get(index)就可以拿到集合中的第index个元素。
还有一个集合的切割方法: stationList3.subList(2, 4)或者stationList3.slice(2..3)
解释一下两个方法的:
subList()方法,包含第2个元素和第3个元素但是不包含第4个元素
slice()方法,包含第2和第3个元素
然后其他的对集合操作的方法和Set集合类似,这里就不赘述了。

 //定义一个数组
        var stationsList = arrayOf("石家庄", "北京", "南京", "上海", "苏州", "上海")
        for (s in stationsList) {
            LogUtils.Loge("stationList:" + s)
        }
        //创建一个有默认值的数组
        var stationList2 = Array(20, { "默认站的名字" })
        for (s in stationList2) {
            LogUtils.Loge("默认名称:stationList2:" + s)
        }

        //创建一个从1--100的数组
        var oneToHundred = Array(100, { i -> i + 1 })
        for (s in oneToHundred) {
            LogUtils.Loge("0到100》oneToHundred:" + s)
        }

        //元素的个数  判断是否为空
        if (oneToHundred.isNotEmpty()) {
            LogUtils.Loge(oneToHundred.count().toString())
        }

        //获取某一个数据
        LogUtils.Loge("站名的第一个" + stationsList.first())
        LogUtils.Loge("站名的最后一个" + stationsList.last())
        LogUtils.Loge("前两个" + stationsList.component1() + stationsList.component2())
        LogUtils.Loge("第两个" + stationsList[2 - 1])
        LogUtils.Loge("第两个" + stationsList.get(2 - 1))

        //筛选重复(把重复的去掉)
        var stationList3 = stationsList.distinct()
        for (s in stationsList) {
            LogUtils.Loge("不重复的数组" + s)
        }

        //把一个数组转化成集合
        val toSet = stationsList.toSet()
        for (s in toSet) {
            LogUtils.Loge("不重复的集合" + s)
        }


        //数组切割  从第二个到第三个,包含前边,不包含后边
        val subList = stationList3.subList(2, 4)
        for (s in subList) {
            LogUtils.Loge("截取数组:" + s)
        }

        //切割数组  从第二个到第三个,包含前边,也包含后边
        val slice = stationList3.slice(2..3)
        for (s in slice) {
            LogUtils.Loge("切割数组:" + s)
        }
//#################################################以上是不可变的数组#############################


        //定义大小可变的数组
        val mutableList2 = mutableListOf("a", "b", "c")
        for (s in mutableList2) {
            LogUtils.Loge("可变数组:" + s)
        }

        //增加一个
        mutableList2.add(2, "e")
        for (s in mutableList2) {
            LogUtils.Loge("可变数组,新增加一个:" + s)
        }

        val mutableList1 = mutableListOf("1", "2", "3")
        //增加一堆
        mutableList2.addAll(mutableList1)
        for (s in mutableList2) {
            LogUtils.Loge("可变数组,新增加一堆:" + s)
        }

        //移除第几个
        mutableList2.removeAt(0)
        for (s in mutableList2) {
            LogUtils.Loge("可变数组,移除第几个:" + s)
        }

        //移除某一个
        mutableList2.remove("e")
        for (s in mutableList2) {
            LogUtils.Loge("可变数组,移除某一个:" + s)
        }

        for (index in mutableList2.indices) {
            LogUtils.Loge("换种写法写循环:" + mutableList2.get(index))
        }

        val list3 = ArrayList<String>()

        list3.add("李")
        list3.add("小")
        list3.add("米")

        list3.remove("李")
        list3.add(0, "牛")
        list3.removeAt(1)
        for (item in list3) {
            LogUtils.Loge("List3集合:" + item)
        }
3.3 最后Map集合:

Map集合和java中的Map相差不大,具体用法可以参照下边的代码。

//创建一个map
        var stationMap = mapOf(Pair("shijiazhuang", "石家庄"), Pair("nanjing", "南京"),
                Pair("suzhou", "苏州"), Pair("shanghai", "上海"), Pair("zhangjiakou", "张家口")
                , Pair("taiyuan", "太原"), Pair("tianjin", "天津"))

        LogUtils.Loge("map数量:" + stationMap.count())
        LogUtils.Loge("map是否位空:" + stationMap.isEmpty())

        //根据key获取values
        LogUtils.Loge(stationMap.get("tianjin"))
        //获取所有的key
        val keys = stationMap.keys
        for (s in keys) {
            LogUtils.Loge("所有的key:" + s)
        }
        //获取所有的values
        val values = stationMap.values
        for (s in values) {
            LogUtils.Loge("所有的values:" + s)
        }

        val toMutableMap = stationMap.toMutableMap()

        toMutableMap.remove("shijiazhuang")
        for (mutableEntry in toMutableMap) {
            LogUtils.Loge("移除某一个:" + mutableEntry)
        }

        toMutableMap["nanjing"] = "南京市"
        for (mutableEntry in toMutableMap) {
            LogUtils.Loge("根据key修改values:" + mutableEntry)
        }
        toMutableMap["cangzhou"] = "沧州"
        for (mutableEntry in toMutableMap) {
            LogUtils.Loge("这样能新增一个:" + mutableEntry)
        }

4、函数/方法

4.1基本方法
 //基本函数
    fun init() {
        /**
         * 调用一个方法
         */
        LogUtils.Loge("调用一个方法:" + makeIntData(1))

        LogUtils.Loge("调用求和方法:" + sum(1, 2).toString())

        LogUtils.Loge("调用求和方法,第二个参数不传递:" + sum(1).toString())

        LogUtils.Loge("调用求和方法,可变参数,第一个:" + sum1(1, 2, 3, 4, 5).toString() + ",第二个:" + sum1(1, 2, 3))

        var intArrayOf = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8)
        LogUtils.Loge("调用求和方法,可变参数,也可以穿一个数组进去:" + sum1(*intArrayOf).toString())

    }


    /**
     * 定义一个入参为int类型的,返回值为String 类型的方法
     */
    private fun makeIntData(number: Int): String {
        return (number + 1).toString()
    }

    /**
     * 定义一个入参为两个int类型 ,第一个必选,第二个不传的时候默认为0,返回只为int 类型,但是可以为null
     * 以及三元运算符的使用
     */
    private fun sum(number: Int?, number1: Int = 0): Int? {
//        if (number != null) {
//            return number + number1
//        } else {
//            return null
//        }
        
        return if (number != null) number + number1 else null
    }

    /**
     * 定义一个可变参数
     */
    private fun sum1(vararg x: Int): Int {
        var sumNumber = 0
        for (i in x) {
            sumNumber += i
        }
        return sumNumber
    }

看一下输出的效果:

11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用一个方法:2###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法:3###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,第二个参数不传递:1###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,可变参数,第一个:15,第二个:6###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,可变参数,也可以穿一个数组进去:36###
4.2高阶函数

高阶函数:
1、参数或者返回值的类型是函数型
函数型:(参数)--》返回值
lambda: 一种无名函数的简写{ (参数)--》函数执行语句}
其他语言称为闭包,即有能力访问其自身范围外的变量
2 、描述任务的结果,而不是使用循环详细推算
map:常用于对集合类型的元素类型整体元转
其lambda中的参数的约定称为it

       //想要把数字转化为汉字
        val a = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        val b = a.map { "第${it}" }
        for (s in b) {
            LogUtils.Loge("整数转换位字符串" + s)
        }


        //闭包
        //filter:对集合类型进行筛选
        //把偶数筛选出来,然后求和
        var sum = 0
        val c = a.filter {
            it % 2 == 0
        }.forEach {
            sum += it
            LogUtils.Loge("闭包中的:" + sum)
        }

        //分组
        val groupBy = a.groupBy { it % 2 == 0 }
        LogUtils.Loge("groupBy" + groupBy)

5、控制流 for\while\when

这个就没啥好说的了,大家看下代码,然后看一下输出的结果,就明白是啥意思,记住具体的写好就好了。

        //循环中的控制   : continue 结束本次循环    ,break结束整个循环
        var stringList = arrayOf("小牛", "太阳", "鹈鹕", "黄蜂" )
        //依次操作一个序列(如集合类型)中的每一项,执行次数是可预测的
        for (s in stringList) {
            LogUtils.Loge("循环:" + s)
        }

        //重复执行
        for (a in 0..10) {
            if (a == 5) {
                continue
            }
            LogUtils.Loge("一直在重复执行" + a)
        }

        //while:循环执行操作,直到条件不成立.例子:计算从1开始,加到多少,和是5050
        var sum = 0//和
        var number = 1//起始数
        var timer = 0//次数
        while (sum < 5050) {
            if (number == 5) {
                break
            }
            timer += 1
            number += 1
            sum += number + 1
            LogUtils.Loge("while:循环" + timer)
        }

        var a = 10
        if (a == 10)
            LogUtils.Loge("a等于10")
        else
            LogUtils.Loge("a不等于10")

        LogUtils.Loge(if (a == 10) "a等于10" else "a!=10")


        //在wen语句中,满足了一个条件,就不去执行下边的了
        when (a) {
//            in 0..11 -> {
//                LogUtils.Loge("a在0到11之间")
//            }

            (20 - 11) -> {
                LogUtils.Loge("a==10")
            }

            is Int->{
                LogUtils.Loge("a是Int类型")
            }

            else -> {
                LogUtils.Loge("a不在0到11之间")
            }
        }

然后看一下输出的结果:

11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:小牛###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:太阳###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:鹈鹕###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:黄蜂###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行0###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行1###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行2###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行3###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行4###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行6###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行7###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行8###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行9###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环1###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环2###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环3###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环4###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a等于10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a等于10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a是Int类型###

6、面向对象编程

这里介绍类的定义、属性、方法以及继承、数据类、枚举类、对象生命和表达式的写法:

 private fun init() {
        var mBook1 = ShoppingBook("如何购物", 50)
        var mBook2 = FoodBook("吃东西", 20, "food")
        LogUtils.Loge(mBook1.toString())
        LogUtils.Loge(mBook2.toString())
        LogUtils.Loge("mBook1.colors" + mBook1.colors)
        LogUtils.Loge("mBook1.address" + mBook1.address)
        LogUtils.Loge("mBook1.number" + mBook1.number)
        LogUtils.Loge("mBook1.newPrice" + mBook1.newPrice)
        mBook1.colors = "绿色"
        LogUtils.Loge("mBook1.colors" + mBook1.colors)
        LogUtils.Loge("mBook1.address" + mBook1.address)
        LogUtils.Loge("mBook1.number" + mBook1.number)
        LogUtils.Loge("mBook1.newPrice" + mBook1.newPrice)

        mBook1.cook()
        mBook2.cook()


        //数据类
        var mUser = User("小米", "123456")
        LogUtils.Loge(mUser.toString())

        //复制
        var mUser2 = mUser.copy(password = "123")
        LogUtils.Loge(mUser2.toString())

        //数据类对象的结构
        var (name, password) = mUser
        LogUtils.Loge("username:$name,$password")

        //列举熟悉
        LogUtils.Loge("${mUser.component1()}${mUser.component2()}")

        LogUtils.Loge("枚举类:" + SexType.values().joinToString())

        val sizeOrdinal = Size.valueOf("M").ordinal
        val sizeName = Size.valueOf("M").name
        LogUtils.Loge("带有构造器的枚举类:" + sizeOrdinal + sizeName)

        val joinToString = Size.values().joinToString { it.name + ":" + it.height }

        LogUtils.Loge("带有构造器的枚举类:" + joinToString)


        //对象表达式
        val baako = object : Chinese("Baako Zaid") {
            override var skin = "black"
        }

        LogUtils.Loge(baako.skin)

        //纯对象表达式:是临时用,无需继承任何类
        val temParking = object {
            var x = 100
        }

        //封装一个类
        NetWorkRequestManager.register()
        //伴生方法与类的关联性强
        IDCard.creat()
    }


    /**
     * 伴生对象:一般用于创建一个类的实例的“工厂”方法
     * 相当于java的静态成员
     */

    class IDCard {
        companion object {
            fun creat() = IDCard()
        }
    }

    //对象声明
    object NetWorkRequestManager {
        fun register() {
            LogUtils.Loge("连接网络")
        }
    }

    /**
     * 对象表达式
     */
    open class Chinese(var name: String) {
        open var skin = "yellow"
    }

    /**
     * 定义一个书的实体
     * 关键字open   ,如果一个类想要被集成,需要在class前加上open关键字
     */

    /**
     * 访问修饰符:
     * private
     * protected  仅子类可见
     * internal  当前模块内可见
     * public
     */
    open class Book constructor(var name: String, var price: Int, var type: String) {
        //普通属性
        open var colors: String = "红色"
        var newPrice: Int = 0
        //组合属性
        var address: String = ""
            get() {
                when (this.colors) {
                    "红色" -> {
                        return "石家庄"
                    }
                    else -> {
                        return "其他"
                    }
                }
            }

        //组合属性也可以影响其他属性
        var number: Int
            get() {
                when (this.address) {
                    "石家庄" -> {
                        return 100
                    }
                    else -> {
                        return 200
                    }
                }
            }
            set(value) {
                when (value) {
                    in 0..199 -> {
                        newPrice = 100
                    }
                    else -> {
                        newPrice = 200
                    }
                }
            }


        //类中的方法
        open fun cook() {
            val menu = arrayOf("番茄炒蛋", "炒土豆", "小米粥")
            val reduce = menu.reduce { s1, s2 -> s1 + "," + s2 }
            LogUtils.Loge("类中的方法:${reduce}")
        }


    }

    /**
     * 类的继承
     */
    class ShoppingBook(name: String, price: Int, type: String = "shopping") : Book(name, price, type) {
        var content = "教你如何购物"

        override fun cook() {
            super.cook()
            var menu = arrayOf("毛血旺", "烤鱼")
            val reduce = menu.reduce { s1, s2 -> s1 + "," + s2 }
            LogUtils.Loge("子类继承父类的方法:${reduce}")
        }
    }

    /**
     * 类的继承
     */
    class FoodBook(name: String, price: Int, type: String) : Book(name, price, type) {
        var content = "如何吃东西才健康"
        //在子类中如果要重写父类的属性,要在父类属性中添加open关键字
        override var colors = "食物黄色"
    }

    /**
     * 数据类
     */
    data class User(var username: String, var password: String)

    /**
     * 枚举类
     */
    enum class SexType {
        男, 女
    }

    /**
     * 带有构造器的枚举类
     */
    enum class Size(val height: Int) {
        S(150), M(160), L(170), XL(180)
    }

7、异常处理以及类型转换

7.1异常处理:

分为两种方式:一种是重要的异常,对程序产生重要影响的,我们要捕获异常,并且处理一下。
第二种是不重要的,在java中是抛出异常,这里抛出异常的写法和java不太一样。
具体看代码:

//捕获异常
        try {
            "g".toInt()
        } catch (e: Exception) {
            LogUtils.Loge(e.toString())
        }

        //抛出异常
        val a: Int? = try {
            "g".toInt()
        } catch (e: Exception) {
            null
        }

        LogUtils.Loge(a.toString())

Log:

11-16 15:09:47.668 4994-4994/com.example.lql.kotlindemo E/###: java.lang.NumberFormatException: Invalid int: "g"###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: null###
7.2类型检查和类型转换:

这里值得说的是类型转换,在kotlin中分为强制类型转换和安全转换,
比如在代码中吧变量C转换成String类型,如果你非常确定C是一个String,那么你就可以使用强制类型转换。但是如果你不确定C是一个String,那么你可能就需要安全转换了。在安全转换中,如果出现错误,最后拿到的值是一个null.但是不影响程序的运行。

        val a = 5
        val b = 6
        val c = if (a > b) "大于" else a - b

        //类型检查
        if (c is String) {
            LogUtils.Loge("长度" + c.length)
        }

        if (c !is String) {
            LogUtils.Loge("整数" + c)
        }


        //类型转换
        try {
            //强制转换
            var d = c as String
            LogUtils.Loge("强制转换:" + d)
        } catch (e: Exception) {
            LogUtils.Loge("强制转换报错了" + e.toString())
        }

        //安全转换
        var e = c as? String
        LogUtils.Loge("安全转换:" + e)

Log:

11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 整数-1###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 强制转换报错了java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 安全转换:null###

好了,先写这些。在下一篇中介绍泛型、接口以及扩展部分的内容。
因为是刚刚开始学习Kotlin,可能对某些概念和语法认识不足,如有错误,希望大家能给予指正!

下一篇《初识Kotlin<下>》

上一篇下一篇

猜你喜欢

热点阅读