美文网首页
Kotlin笔记

Kotlin笔记

作者: 金馆长说 | 来源:发表于2018-08-05 16:59 被阅读10次

    函数

    kotlin 函数以fun来标识,使用方式和java一样,同一类使用直接调用,如果是通过类引用则使用 '类名.model()' 来引用

    fun mode(){
            //...
        }
    

    当前类使用

     var value = model()
    

    其他类

    类名.mode()
    

    根据返回的值自动推断类型 return string Type

    fun model() = "jinwei" + 20
    

    根据返回的值自动推断类型 return int Type

     fun model2() = 32
    
    

    等价于 fun model3()

    fun model3() = Unit
    

    变量

    标签

    标签是为了方便跳转到指定位置,常和 break 和 continue 搭配使用。但是Kotlin中的标签还可以和 return 搭配使用,表示在标签处返回。

    simple
    这段代码的j==2时调用了break,所以这次的执行被返回了出去,继续下一次i的执行;

      fun f() {
                for (i in 0..10) {
                        for (j in 0..2) {
                            if (j == 2) {
                                break
                            }
                        }
                    }
            }
    

    如果我们希望break调整个循环体,就可以用标签了。

    lable@
    

    这种方式命名,name自己定义后面跟入一个@符号

    这次加入了标签,break到了loop标签的地方。直接就会结束标签定义的地方,继续往下执行。

    fun f() {
                loop@for (i in 0..10) {
                    for (j in 0..2) {
                        if (i == 2) {
                            break@loop
                        }
                    }
                }
                System.out.println("这里会继续执行")
            }
    

    标签处返回

    fun main(args: Array<String>) {
        val ints = intArrayOf(1, 2, 3, 0, 4, 5, 6)
        ints.forEach {
            if (it == 0) return
            print(it)
        }
    }
    

    上面代码中的 return 指的是从 main 函数中返回,因为 main 函数是最直接包围它的函数。所以运行结果为:

    123

    如果想要从 forEach 中的 lambda 表达式中返回,就需要使用标签了。代码如下,在 lambda 表达式的前面声明一个标签lit@,然后在 return 处使用标签,即[return@lit](mailto:return@lit)

    val ints = intArrayOf(1, 2, 3, 0, 4, 5, 6)
    ints.forEach lit@ {
        if (it == 0) return@lit
        print(it)
    }
    
    

    运行结果为:

    123456

    可变操作参数
    参数的最后一个或者第一个可以被vararg标记,变量会变成array类型,类似于java中的 int...可变参数一样。

     fun mode2(vararg ts: Int) {
            System.out.print(ts[3])
        }
    

    伸展(spread)操作符,可以将数组传递给函数。
    可以看到在变量的前面加入了*符号

        var v = intArrayOf(1, 2)
        mode2(1, 1, *v)
    

    中缀
    中缀表示法三个条件

    1. 它们必须是成员函数或扩展函数
    2. 它们必须只有一个参数;
    3. 其参数不得接受可变数量的参数且不能有默认值
    • Int.model代表只能通过Int来调用或者是其他的类型,基本类型,对象都可以。
    • this代表调用的的对象
    • 这里只能通过Int来调用,其他类型会编译错误 1 model2 2
     infix fun Int.model2(v: Int): Int {
            System.out.print("中缀函数,实例是:$this,参数是$v")
            return v
        }
    

    中缀函数调用的优先级低于算术操作符、类型转换以及 rangeTo 操作符

     1 model2 2 * 2
    

    等于 1 model2(2*2) 先会运行有算数运算符的逻辑,才去执行方法的调用

    另一方面,中缀函数调用的优先级高于布尔操作符 && 与 ||、is- 与 in- 检测以及其他一些操作符

     1 model2 2 == 2 
    

    先执行前面的中缀,在执行布尔运行

    局部函数
    局部函数,内部函数可以访问外部变量。

     fun model3() {
            var value = 20
            fun testModel() {
                System.out.print(value)
            }
        }
    

    成员函数
    在类或者对象的内部声明,通过实例来调用。

     class Simple {
            fun foo() {
    
            }
        }
    

    泛型函数

    fun <T> getTbean(item: T): T {
    
            return item
        }
    

    数组
    kotlin 使用Array来表示数组,通过库函数arrayOf来创建。

     fun test() {
            // 创建一个 Array<String> 初始化为 ["0", "1", "4", "9", "16"]
            val asc = Array(5) { i -> (i * i).toString() }
    
    
            //初始化string数组,只有一个元素
            val arrayOf = arrayOf(String)
            //初始化MainClass数组,只有一个元素
            val arrayOf1 = arrayOf(MainClass)
    
            //指定大小,元素为null的数组
            val arrayOfNulls = arrayOfNulls<String>(size = 2)
        }
    

    字符串

    fun stringTest() {
            val s = "Hello, world!"
            println("$s.length is ${s.length}") // 输出“abc.length is 3”
        }
    

    区间

    0..10执行0-10直接的数

     for (item in 0..10) {
    
            }
    

    倒序
    执行4-1之间的数

    for (i in 4 downTo 1) print(i)
    

    step
    step 3代表每隔3打印一次 打印124

     for (i in 1..10 step 3) println(i)
    

    要创建一个不包括其结束元素的区间,可以使用 until 函数

            for (i in 1 until 10) {
                // i in [1, 10) 排除了 10
                println(i)
            }
    

    对象表达式
    类似于java中的匿名内部类

           //这是一个对象
            var a = object {
                fun create() {}
            }
    
            object C {}
    

    伴生对象
    这是一个伴生对象,可以直接通过类名来使用A内部的方法和变量

        companion object A {
              fun create() {}
          }
    

    数据类
    数据类通过data 来标识类,特有以下特点。
    编译器自动从主构造函数中声明的所有属性导出以下成员:

    • equals()/hashCode() 对;
    • toString() 格式是 "User(name=John, age=42)"
    • componentN() 函数 按声明顺序对应于所有属性;
    • copy() 函数(见下文)。
    data class JinBean(var name: String, var age: Int) {}
    

    普通对象是不会具有这类特性的。

                var data = JinBean("JINWEI", 20)
                var data2 = data.copy()
                data2.age = 22
                println(data.toString())
                println(data2.toString())
    

    输出 20
    输出 22
    通过copy没有影响到对方的值,如果没有data的话。这里的输出会是一样的,因为他们指向的引用到是同一个对象。

    内部类

     class TT2 {
    
            var aa = 220
    
            //内部类无法访问外部成员
            class tt2 {
                fun m2() {
    //                aa = 20////无法访问
                }
            }
    
    
            //inner标记的类会带有一个外部类对象的引用,可以访问外部成员。
            inner class tt3 {
    
                fun m2() {
                    aa = 20
                }
            }
        }
    
    

    解构

    定义一个实体类

     data class P2(var age: Int, var name: String) {
    
            var number = 2
    
            operator fun component3(): Int {
                return number
            }
        }
    
    1. 解构声明,意思就是通过var(x,x) = p的方式把对象的构造参数,通过拆解的方式单独声明一个变量。
      var pp: P2 = P2(20, "jw")
      var (age, name) = pp
      println(age)
      println(name)
    

    在Kotlin-数据类中,我们已经了解到编译器会根据主构造器中声明的全部属性, 自动推断产生componentN() 函数群, 这些函数与类的属性对应, 函数名中的数字1到N,与属性的声明顺序一致
    解构声明在编译时将被分解为以下代码:

    val name = person.component1()
    val age = person.component2()
    
    
    1. 解构for循环
                var p1 = P2(20, "jw")
                var p2 = P2(20, "jw")
                var p3 = P2(20, "jw")
                val listOf = listOf(p1, p2, p3)
                for ((name, age) in listOf) {
                    println("age=$age name=$name")
                }
    

    自定义componentN,默认解构只会解构造函数里面的变量,如果需要解构我们自己的成员变量,就需要自定义了。
    对于自定义的componentN(),需要注意以下几点:

    1. componentN()函数需要标记为 operator , 才可以在解构声明中使用
    2. componentN()函数的返回值类型必须与属性类型一致
      var p4 = P2(20, "jw")
      p4.number = 200
      var (name, age, sex) = p4
      println("age=$age name=$name number$sex")
    
    1. Map
               var p11 = P2(210, "jw")
                var p22 = P2(210, "jw")
                var p32 = P2(210, "jw")
                val mutableMapOf = mutableMapOf<String, P2>()
                mutableMapOf.put("1", p11)
                mutableMapOf.put("2", p22)
                mutableMapOf.put("3", p32)
                for ((age, name) in mutableMapOf) {
                    println("age=$age name=$name ")
                }
    

    安全类型转换
    如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException。 另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null:

     var v1: String? = ""
     var v2: Int? = v1 as Int
    
    这样转换会出现异常
    Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        at kt.JAVA2$Companion.main(JAVA2.kt:57)
        at kt.JAVA2.main(JAVA2.kt)
    

    使用安全转换

     var v1: String? = ""
     var v2: Int? = v1 as? Int
    

    as?这样转换不会报错,会返回null。

    相关文章

      网友评论

          本文标题:Kotlin笔记

          本文链接:https://www.haomeiwen.com/subject/usibvftx.html