Kotlin学习笔记0x03 标签 标签的格式为标识符后加上一个@ 例如a@,b@ 标签可以用于控制return break continue的跳转行为1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fun main (args: Array <String >) { returnDemo() } fun returnDemo () { println("Start " +::returnDemo.name) val intArray = intArrayOf(1 ,2 ,3 ,4 ,5 ) intArray.forEach here@ { if (it == 3 ){ return @here } println(it) } println("End " +::returnDemo.name) }
1 2 3 4 5 6 Start returnDemo 1 2 4 5 End returnDemo
Lambda函数/Lambda表达式 break配合@标识符 结束嵌套的for循环1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fun main (args: Array <String >) { breakDemo() } fun breakDemo () { println("----------" ) outer@ for (outer in 1. .5 ){ for (inner in 1. .10 ){ println("inner=$inner " ) println("outer=$outer " ) if (inner % 2 ==0 ){ break @outer } } } println("**********" ) }
1 2 3 4 5 6 ---------- inner =1 outer=1 inner =2 outer=1 **********
为了代码可读性,可以显示的用标识符来表示所要跳转的循环体 ```Kotlin fun main(args: Array) { breakDemo2() } fun breakDemo2() { println(“———-“) outer@ for(outer in 1..5){ inner@ for(inner in 1..10){ print(“outer=$outer,”) println(“inner=$inner”) if(inner % 2==0){ break@inner //break@outer } } } println(“**********”) }1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ````Kotlin ---------- outer=1,inner=1 outer=1,inner=2 outer=2,inner=1 outer=2,inner=2 outer=3,inner=1 outer=3,inner=2 outer=4,inner=1 outer=4,inner=2 outer=5,inner=1 outer=5,inner=2 ********** //break@outer的情况 ---------- outer=1,inner=1 outer=1,inner=2 **********
throw表达式 在Kotlin中throw是表达式,它的类型是Nothing,这种类型没有值,与C Java中的void 具有相同的意思
在代码中使用Nothing来标记无返回的函数1 2 3 4 fun main (args: Array <String >) { fail("s" ) } fun fail (msg:String ) :Nothing {throw IllegalArgumentException("at fail($msg )" )}
1 2 3 Exception in thread "main" java.lang.IllegalArgumentException: at fail(s) at com.easy.kotlin.A_multi_language_HelloKt.fail(A multi-language Hello.kt:9 ) at com.easy.kotlin.A_multi_language_HelloKt.main(A multi-language Hello.kt:7 )
throw表达式的值可以付给变量,但需要显式的声明类型为Nothing,这个变量也无法当作参数参数传给函数1 2 3 4 fun main (args: Array <String >) { val ex: Nothing = throw Exception("EX" ) println(ex) }
1 2 3 4 5 6 7 8 9 10 11 Error: Overload resolution ambiguity: @InlineOnly public inline fun println (message: Any ?) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Boolean ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Byte ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Char ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: CharArray ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Double ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Float ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Int ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Long ) : Unit defined in kotlin.io@InlineOnly public inline fun println (message: Short ) : Unit defined in kotlin.io
this 关键字 this 表示当前对象的引用,我们可以使用this来引用变量或者成员函数,也可以使用return来返回某个类的引用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun main (args: Array <String >) { val demo = ThisDemo() println(demo.whatIsThis()) } class ThisDemo { val thisis="THIS IS" fun whatIsThis () :ThisDemo{ println(this .thisis) this .howIsThis() return this } fun howIsThis () { println("HOW IS THIS?" ) } }
1 2 3 THIS IS HOW IS THIS? com.easy.kotlin.ThisDemo@ 5305068a
在扩展函数或者带接收者的函数字面值中,this表示在点左侧传递的接受者参数1 2 3 4 5 6 fun main (args: Array <String >) { val sum = fun Int .(x: Int ) =this +x println(1. sum(2 )) val str = fun String.(s:String ) =this +s println("old" .str("new" )) }
如果this没有限定符,那么它指的就是最内层包含它的作用域,如果想要引用其他作用于中的this,可以使用this@label标签1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Outer { val oh ="Oh" inner class Inner { fun m () { val outer = this @Outer val inner = this @Inner val pthis =this println("outer=" +outer) println("inner=" +inner ) println("pthis=" +pthis) println(this @Outer .oh) val fun1 = hello@ fun String.() { val d1 = this println("d1" +d1) } val fun2={s:String-> val d2 = this println("d2=$d2 " ) } "abc" .fun1() fun2 } } } fun main (args:Array <String >) { val outer = Outer() outer.Inner().m() }
1 2 3 4 5 outer=com.easy.kotlin.Outer@ 5305068a inner =com.easy.kotlin.Outer$Inner@ 1f32e575pthis=com.easy.kotlin.Outer$Inner@ 1f32e575 Oh d1abc
super关键字 super关键字指向其父类的引用
敲到这里 我突然产生了一个疑问,我也不知道我打字的时候是盲打还是看着打的 至少符号多数是看着打的 然后我就去百度下 其他人敲代码是盲打还是看着打, 然后,看到了一个 关于盲人敲代码的文章盲人程序员是如何编程的 文章的最后提到了 盲人做梦…勾起了我的好奇心1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 open class Father { open val firstName = "Chen" open val lastName ="Jason" fun ff () { println("FFF" ) } } class Son :Father { override var firstName = super .firstName override var lastName = "Jack" constructor (){ } constructor (lastName:String){ this .lastName = lastName } fun love () { super .ff() println(super .firstName+" " +super .lastName+" Love " +this .firstName+" " +this .lastName) } } fun main (args:Array <String >) { val son1 = Son("Harry" ) val son2 = Son() son1.love() son2.love() }
1 2 3 4 FFF Chen Jason Love Chen Harry FFF Chen Jason Love Chen Jack
运算符的重载
表达式
对应的函数
+a
a.unaryPlus()
-a
a.unaryMinus()
!a
a.not()
a+b
a.plus(b)
a-b
a.minus(b)
a*b
a.times(b)
a/b
a.div(b)
a%b
a.rem(b),a.mod(b)
a..b
a.rangeTo(b)
表达式
对应的函数
返回值
a++
a.inc()
a
a—
a.dec()
a
++a
a.inc()
a+1
—a
a.dec()
a-1
运算符 - 的重载 1 2 3 4 5 6 7 8 data class Point (val x: Int , val y: Int )operator fun Point.unaryMinus () = Point(-x, -y)fun main (args:Array <String >) { val p = Point(6 , 7 ) val np= -p println(np) }
运算符 + 的重载 1 2 3 4 5 6 7 8 9 10 data class Point (val x: Int , val y: Int )operator fun Point.plus (increment: Int ) :Point=Point(x+increment,y+increment)operator fun Point.plus (inc: Point ) :Point = Point(x+inc.x,y+inc.y)fun main (args:Array <String >) { val p = Point(6 , 7 ) val np= p+1 val np2 = p+p println(np) println(np2) }
1 2 Point(x=7 , y=8 ) Point(x=12 , y=14 )
in操作符
表达式
对应函数
a in b
b.contains(a)
a !in b
!b.contains(a)
索引访问操作符
表达式
对应函数
a[i]
a.get(i)
a[i]
a.set(i,b)
调用操作符
表达式
对应函数
a()
a.invoke()
a(i)
a.invoke(i)
计算并赋赋值
表达式
对应函数
a+=b
a.plusAssign(b)
a-=b
a.minusAssign(b)
a/=b
a.divAssign(b)
a*=b
a.timesAssign(b)
a%=b
a.modAssign(b)
Elvis 操作符 ?: 在Kotlin中,Elvis操作符特定是跟null进行比较
1 2 3 y = x?:0 val y = if (x!=null )x else 0
主要用作 null 安全检查 Elvis操作符的命名灵感来自于猫王的发型风格,不过我去百度了下猫王(埃尔维斯·普雷斯利Elvis Presley),感觉没多大联系,Kotlin创造者的想法真是奇怪 Kotlin中并没有xxx?true:false这样的三元运算符取而代之的是if(true) true else false
比较操作符
表达式
对应函数
a>b
a.compareTo(b) > 0
a<b
a.compareTo(b) < 0
a>=b
a.compareTo(b) >= 0
a<=b
a.compareTo(b) <= 0
compareTo返回一个Int值
infix函数自定义中缀操作符 1 2 3 4 5 6 7 8 9 data class Person (val name:String,val age: Int )infix fun Person.grow (years:Int ) :Person{ return Person(name,age+years) } fun main (args:Array <String >) { val person = Person("Jack" ,11 ) println(person.grow(1 )) println(person grow 9 ) }
1 2 Person(name=Jack, age=12 ) Person(name=Jack, age=20 )
你可能会觉得 这个调用一个类内部函数没多大区别啊,别急看看下面的例子
1 2 3 4 5 6 7 8 9 10 infix fun Int .a (x:Int ) =this +xinfix fun String.说(s:String ) =this +sfun main (args:Array <String >) { println(10. a(1 )) println(1 a 2 ) println("你拍一" .说(",我拍二" )) println("你拍二" 说 ",我还是拍一" ) val 我的天啊 = "不存在的" println(我的天啊) }
1 2 3 4 5 11 3 你拍一,我拍二 你拍二,我还是拍一 不存在的
是的 就是有这种操作
函数扩展和属性扩展 Kotlin 支持 扩展函数 和 扩展属性.能够扩展一个类的新功能而无需继承该类 ,大多数情况下我们在顶层定义扩展,即直接在包里
1 2 3 4 5 6 package com.easy.kotlinval <T> List<T>.lastIndex: Int get () = size -1 fun String.notEmpty () :Boolean { return !this .isEmpty() }
若要使用其他包的扩展,我们需要在调用方内导入它
1 2 3 4 5 6 7 package com.example.usageimport foo.bar.gooimport foo.bar.*fun uage (baz: Baz ) { baz.goo() }
扩展函数 1 2 3 4 5 6 7 fun String.notEmpty () :Boolean =!this .isEmpty()fun main (args:Array <String >) { println("a" .notEmpty()) println(!"123" .isEmpty()) }
看到这里,你能会想,这个扩展函数和infix函数有啥区别的,碰巧的是,我也有这样疑问,于是做了个试验,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fun main (args:Array <String >) { println("a" .notEmpty("cct" ,2 )) println("a" .notEmpty()) println("b" isnotEmpty "asd" ) println("b" .isnotEmpty("asd" )) } fun String.notEmpty () :String{ return this +":String.notEmpty()" } fun String.notEmpty (s:String ,n:Int ) :String{ return this +s+":String.notEmpty(s:String)" +n.toString() } infix fun String.isnotEmpty (s:String ) :String{ return this +s+":String.isnotEmpty(s:String)" }
1 2 3 4 acct:String.notEmpty(s:String)2 a:String.notEmpty() basd:String.isnotEmpty(s:String) basd:String.isnotEmpty(s:String)
infix 函数有且只有一个参数,拓展函数可以有任意个参数,只有用infix符号修饰的函数才可以实现中缀操作符调用(例如”b” isnotEmpty “asd”)
扩展属性 1 2 3 4 5 6 7 8 fun main (args:Array <String >) { val mList = mutableListOf<Int >(100 ,200 ,300 ,400 ,500 ) println(mList) println(mList.lastIndex) } val <T> List<T>.lastIndex: Int get (){ return -size }
1 2 [100 , 200 , 300 , 400 , 500 ] -5
空指针安全 在Kotlin中 null 等同于空指针 一个非空引用不能直接复制为空 对于非空引用,可以直接调用它的方法或者访问它的属性
如果允许为空,就得在变量类型后面加上一个?表示这个变量允许为空 对于允许为空的引用,不能直接调用他的方法和属性,得使用安全调用(使用.?)或者非空断言调用(或者使用!!.)
1 2 3 4 5 6 7 8 9 10 11 fun main (args:Array <String >) { var s1: String="s" var s2: String? s2=null println(s1.length) println(s2) println(s2?.length) println(s2!!.length) }
1 2 3 4 5 6 7 1 null null Exception in thread "main" kotlin.KotlinNullPointerException at com.easy.kotlin.A_multi_language_HelloKt.main(A multi-language Hello.kt:16)
参考资料
在线Kotlin IDE
To Be Continue