Kotlin笔记

函数

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。

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

推荐阅读更多精彩内容