Kotlin浅谈

简介

       Kotlin是一门静态语言,支持多种平台,包括移动端、服务端以及浏览器端,此外,Kotlin还是一门融合了面向对象与函数式编程的语言,支持泛型、安全的空判断,并且Kotlin与Java可以做到完全的交互。

Kotlin特点
  1. 代码量少且代码末尾没有分号。
  2. 被调用的方法需放到上边。
  3. Kotlin是空安全的:在编译时期就处理了各种null的情况,避免了执行时异常。
  4. 它可扩展函数:我们也可以扩展任意类的更多的特性。
  5. 它也是函数式的:比如,使用lambda表达式来更方便地解决问题。
  6. 高度互操作性:你可以继续使用所有用Java写的代码和库,甚至可以在一个项目中使用Kotlin和Java两种语言混合编程
As安装插件及添加依赖:

插件安装:File->setting->plugin->Kotlin
依赖添加:Tools ->Kotlin->Configure Kotlin in Project 选定模块后会自动添加依赖

Kotlin的一般属性:
  • 作用域:
    public:默认,总是可见
    internal:同模块可见
    protected:类似于private,但对子类也可见
    private:声明范围与同模块的子作用域可见,val常量和var变量,默认都是private的

  • 三种方法:
    扩展方法:Kotlin中的方法可以直接定义在文件中,而不需要依赖于任何的类;
    成员方法:写在class或object中的方法;
    本地方法: 定义在方法内部的方法,可以访问外部函数的私有成员

关键字:

var:定义变量,默认是private的
val:定义常量,默认是private的
fun:定义方法,默认是public final
Unit:默认方法返回值,类似于Java中的void,可以理解成返回一个没有意义的值
vararg:可变参数
$:字符串模板(取值)
位运算符:or(按位或),and(按位与),shl(有符号左移),shr(有符号右移),
ushr(无符号右移),xor(按位异或),inv(按位取反)
in:在某个范围中
downTo:递减,循环时可用,每次减1
step:步长,循环时可用,设置每次循环的增加或减少的量
when:Kotlin中增强版的switch,可以匹配值,范围,类型与参数
is:判断类型用,类似于Java中的instanceof()
as:设置别名

数据类型

Kotlin中数字相关的内置类型有: byte、short、Int、Long、Float、Double

需要注意的:
1. 没有自动向上转型,比如Int转Long,需要自己调toXxx方法转;
2.Long类型结尾必须为大写的L,不能为小写,比如1024L
3.字符Char不是Number,用单引号来声明,比如'c',不能像Java一样直接拿来当数字使,如果你想把Char的值给Int,需要调toInt()方法
4.Boolean的值为true或false
5.Kotlin不支持8进制,十六进制0x开头,二进制0b开头
6.位运算符,Java中的与或运算符用:|和&,kotlin中使用or和and关键字来替代其他运算符也有分别的关键字替代:shl(有符号左移),shr(有符号右移),ushr(无符号右移),xor(按位异或),inv(按位取反)

数组:
  • 数组创建:

    定长数组:val fixedSizeArray = arrayOfNulls<Int>(10)
    空数组: val empty = emptyArray<Int>()
    装箱操作:val arr = arrayOf(1, 2, 3) //还有其他比如IntArrayOf,BooleanArrayOf等
    闭包初始化:
    val array = Array(10,{num-> num})
    for (i in 0..9) print(array[i])

  • 数组遍历:

    for (i in array) { //元素遍历
    print(i)
    }

    for (i in array.indices) { //根据下标遍历
    print(array[i])
    }

when语句(增强版Switch)

when语句可以匹配类型,值和范围还有参数,而且不用写break语句
例:匹配值与范围

 var result = 99
 when (result) {
   100 -> println("sss")
   99 -> println("ss")
   in 95..99 -> println("s")
   in 90..94 -> println("a")
   in 80..89 -> println("A")
   else -> println("failed")
 }

例:匹配类型(只能匹配变量的类型,或else)

  when (result) {
      is Int -> println("Int") //暂时测试只有Int类型可以
      else -> println("非Int")
    }

例:匹配参数

fun doSomeThing(x: Int) = -1 * x //必须要放到使用者上边才能识别
   when (result) {
     doSomeThing(result) -> println("$result")
     else -> println("else:$result") //输出结果:else :99

例:when 代替 if-else if 。如果没有任何参数提供,那么分支的条件就是简单的布尔表达式,当条件为真时执行相应的分支:

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}
操作符介绍
  1. ?:表示当前对象这个对象可能为空,如:

    //在变量类型后面加上问号,代表该变量是可空变量 
    var name: String? = "zhangsan"  
    
    //如果str不能转为Int类型,则返回null
    fun parseInt(str: String): Int? { 
      val toInt = str.toInt()
      return toInt
    }
    
    fun parseInt(str:String)=str.toInt() //缩写方式,因为它能自动推测出返回值类型
    
    b?.length //如果 b非空,就返回 b.length ,否则返回 null,这个表达式的类型是 Int 
    
      val min = if (2 > 4) {
          "2da"
        }else {
          9 //可以返回不同类型,但必须有值,或引入Unit类
          7 //在if语句块的最后才是最终有效的结果
        }
    
  2. !!:表示当前对象不为空的情况下执行

    val l: Int = if (b != null) b.length else -1 等价于:val l = b?.length ?: -1 
    //缩略型定义方法: var i = 9  等价于:  var i: Int = 9
    
  3. ==号与===号区别
    ==判断值是否相等;
    ===判断值及引用是否完全相等;

  4. : 符号,用于类名后表示继承,用于变量后限定变量类型

  5. .. :区间符号

    if (i in 1..10) { // 等同于 1 <= i && i <= 10
        println(i)
    }
    //使用until函数,创建一个不包括其结束元素的区间
    for (i in 1 until 10) {   //范围[1, 10),不会执行的写法:for (i in 10 until 1)
         println(i)
    }
    
    for (i in 1..4) print(i) // 输出“1234”
    
    for (i in 4..1) print(i) // 注意:这样写什么都不输出
    
    for (i in 4 downTo 1) print(i) // 输出“4321”
    
    for (i in 1..4 step 2) print(i) // 输出“13”,注意:step指定了步长为2
    
    for (i in 4 downTo 1 step 2) print(i) // 输出“42”
    
    for (str in "didala"){ //kotlin还支持字符串遍历
      LogUtils.d(str.toString())
    }
    
  6. _(下划线)

    data class Book(var id: Int, var name: String) //其中Book声明了id,name两个变量。解构时若只要id一个变量时,可以这么做:
    
    val book = Book(1, "英语")
    val (id, _) = book //提取book中某几项,等价于 id = book.id;
    Log.d("LogTag", id)
    
  7. ::符号

    //得到类的Class对象
    startActivity(Intent(this@KotlinActivity, MainActivity::class.java))
    
    //内联函数和reified后续介绍
    inline  fun <reified T> Gson.fromJson(json:String):T {
        return fromJson(json, T::class.java)
    }
    
    //方法引用
    var setBook = setOf<String>("hello", "hi", "你好")
    //setBook.forEach { print(it)} //it是forEach内部隐藏的参数
    setBook.forEach(::print) //var、val在不同场景下,会出现不同方法,如此时的forEach()
    
  8. @限定this符号

    class User {
        inner class State{
            fun getUser(): User{
                //返回User
                return this@User
            }
            fun getState(): State{
                //返回State
                return this@State
            }
        }
    }
    
  9. @作为标签,跳出循环for或forEach

    loop@ for (itemA in arraysA) {
         var i : Int = 0
          for (itemB in arraysB) {
             i++
             if (itemB > 2) {
                 break@loop //注意写法
             }
    
             println("itemB:$itemB") //$符号在kotlin中才表示引用某个参数,作用类似于java中的%s
         }
    }
    
  10. @JvmOverloads方法自动重载

    class Overloads {
        @JvmOverloads
        fun overloaded(a: Int, b: Int = 0, c: Int = 1){
            println("$a, $b, $c")
        }
    }
    
     //引用时:  
        overloads.overloaded(1, 2, 3);
        overloads.overloaded(1);
        overloads.overloaded(1,3);
    
  11. vararg关键字
    代表可变参数,只能一个个传值,不能直接使用外部Array,除非使用 ***** 符号表示将Array中所有的元素都当做参数处理

     fun sum(vararg numbers:Int): Int {
        var result = 0
        for (num in numbers) {
        result += num
      }
      return result
    }
    
    //引用时:
       val array = intArrayOf(6,7,8,9)
       sum(1,2,3,4,*array)
    
  12. 变量赋值

  • 标签法:

    fun fun_run(){
        //方法赋值最初版,可将run理解为一级函数名(固定不变的),outer为二级函数名
        var i: Int = run (outer@{
          return@outer 2
        })
    
        //简化版
        i = run outer@{
          return@outer 2
        }
    
        //精简版
        i = run {
          return@run 1
        }
    
        println("i:$i")
    }
    
    • 直接赋值法:
     private val inds: String? = "dfsfs"
    
    • if()赋值法:
      private val inds2: String? = if (true) {
               "dfsfs"
             } else "dfsfs"
    
    • invoke()赋值法(同时也能用于方法的调用执行):
    // 一个参数,Unit当于java中的void,表示返回一个没有意义的值
    var callback: ((str: String) -> Unit)? = null //此步可理解为在定义类型
    callback = { println(it)}  //调用invoke()时执行
    //因为返回值用的是Unit,所以功能等同于调用方法
    callback?.invoke("hello")
    println("LogTag: ${callback.toString()}") //结果:a.c.a.a<java.lang.String, a.b>
    
    //两个参数
    var callback2: ((name: String, age: Int) -> Unit)? = null
    callback2 = { hello: String, world: Int -> println("$hello's age is $world") }  //结果:Tom's age is 22
    callback2?.invoke("Tom", 22)
    
    var callback3 :((num1:Int, num2: Int)->String)? = null //这里定义invoke()后的值是String类型
    //类型可以推断
    callback3 = { num1, num2 ->
        var res:Int = num1 + num2
        res.toString() //在代码最后,必须对应String类型
    }
    
    println("LogTagggg: $callback3") //结果: a.c.a.a<java.lang.String, a.b>
    println("LogTagggg: ${callback3?.invoke(1, 2)}") //结果:3,所以invoke()后的值才是我们需要的结果
    
    
  1. data关键字,适用于解析类

    data class User( 
        var id: Long,
        var name: String,
        var url: String,
        var mbid: String)  //这里用是()非{}
    
    //相当于:
    
    public class User{
        public long id;
        public String name;
        public String url;
        public String mbid;
    }
    
    //在kotlin中 data 修饰符 = java中 public + getter + setter + toString + equals + hashCode
    
    
  2. Bean解析:

    inline fun <reified T: Any> Gson.fromJsonNew(json: String): T{
    //封装了`Gson.fromJson(String json , Class<T> classOf)`方法
      return fromJson(json, T::class.java)
    }
    
    fun main() {
      val json = "{id:10,url:'url',mbid:'mbid',name:'test'}"
      var result : Bean =  Gson().fromJsonNew(json)
      println("LogTagggg:"+result.id.toString() + ","+result.name)
    }
    
  3. 扩展方法
    可以给任何类添加函数(View,Context等),例如:

    fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { 
        Toast.makeText(getActivity(), message, duration).show()
    }
    
     //执行时调用:fragment.toast("Hello world!")
    

    注意:Kotlin 的方法扩展并不是真正修改了对应的类文件,而是在编译器和 IDE 方面做了处理。使我们看起来像是扩展了方法。

AS中java和kotlin 的代码相互转换:
  • java ->kotlin4种方法:

    1.ctrl + shift + a 快捷键 输入Convert Java File to Kotlin File
    2. ctrl +alt + shift + k 将 Java 代码转换为 Kotlin
    3.打开要转换的java文件,然后选择 Code -> Convert Java File to Kotlin File (在最底部)
    4.鼠标移到java目录下的任意文件位置,鼠标右键后选new->Kotlin File/class(它默认都会在java目录下创建一个.kt文件),最后将要转换的java代码复制到该.kt文件中即会自动完成转换;

  • kotlin ->java:

    先Tools>Kotlin>Show Kotlin Bytecode,然后点击Decompile

参考: https://blog.csdn.net/zxc123e/article/details/73368781

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

推荐阅读更多精彩内容