kotlin 常见 关键词

1、 componentX (多声明)

val f1 = Forecast(Date(), 27.5f, "Shinny")
val (date, temperature, details) = f1
//=======================
// 上面的多声明会被编译成下面的代码
val date = f1.component1()
val temperature = f1.component2()
val details = f1.copmponent3()
// 映射对象的每一个属性到一个变量中,这就是 多声明。
// object class 默认具有该属性。但普通 class 想要具有这种属性,需要这样做:
class person(val name: String, val age: Int) {
    operator fun component1(): String {
        return name
    }
    operator fun component2(): Int {
        return age
    }
}

val 必须有: 用来保存在 component1 和 component2 中返回构造函数传进来的参数的。
operator 暂时还不明真相,IDE 提示的。 操作符重载,函数名为操作符名(即系统默认的关键词,此处为 component1,component2).当使用该操作时,自己重写的操作会覆盖系统默认的操作。

// 常见用法:该特性功能强大,可以极大的简化代码量。 如 map 中的扩展函数实现,允许在迭代时使用 key value
for ((key, value) in map) {
    Log.d("map","key:$key, value:$value")
}

2、 Companion objects (伴生对象)

类似于 java 中的 静态属性或方法,可以表示一个类中的静态属性、常量、函数。

3、with function

 > 包含在 kotlin 的标准函数库中。接收一个对象和一个扩展函数作为它的参数,然后使这个对象扩展这个函数。表示所有在括号中编写的代码都是作为对象(第一个参数)的一个扩展函数,可以就像 this 一样使用所有它的 public 方法和属性。当针对同一个对象做很多操作时非常有利于简化代码。

4、 operator 操作符重载

  > Kotlin 有一些固定数量象征性的操作符,可以在任何类中很容易地使用。方法是创建一个方法,方法名为保留的操作符关键字,这样就可以让这个操作符的行为映射到这个方法。
一元操作符
操作符 函数
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a++ a.inc()
a-- a.dec()
二元操作符
操作符 函数
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.mod(b)
a..b a.rangeTo(b)
a in b a.contains(b)
a !In b !a.contains(b)
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.modAssign(b)
数组操作符
操作符 函数
a[i] a.get(i)
a[i,j] a.get(i,j)
a[i_1,...,i_n] a.get(i_1,...,i_n)
a[i] = b a.set(i,b)
a[i,j] = b a.set(i,j,b)
a[i_1,...,i_n] = b a.set(i_1,...,i_n,b)
等于操作符
操作符 函数
a == b a?.equals(b)?:b === null
a != b !(a?.equals(b)?: b === null)
函数调用操作符
操作符 函数
a(i) a.invoke(i)
a(i,j) a.invoke(i,j)
a(i_1,...,i_n) a.invoke(i_1,...,i_n)

3、 lambda

函数里定义 lambda 表达式形参

 fun setOnClickListener(listener: (View) -> Unit)
 // 表达式通过参数的形式被定义在箭头的左边(被圆括号包围),然后在箭头的右边返回结果。该例中,接收一个 View, 返回 Unit

调用

view.setOnClickListener({ toast("clicked")})
// 当定义了一个方法,必须使用大括号包围,然后在箭头的左边指定参数,在箭头的右边返回函数执行的结果。如果左边的参数没有使用到,可以省略左边的参数:
view.setOnClickListener({ toast("clicked")})
//如果这个函数的最后一个参数是一个函数,可以把这个函数移动到圆括号外:
view.setOnClickListener() { toast("clicked")}
// 最后,如果这个函数只有一个参数,可以省略这个圆括号
view.setOnClickListener { toast("clicked")}

4、 inline (内联函数)

内联函数与普通的函数有点不同。一个内联函数会在编译的时候被替换掉,而不是真正的方法调用。这在译写情况下可以减少内存分配和运行时开销。例如,有一函数只接收一个函数作为它的参数。如果是普通函数,内部会创建一个含有那个函数的对象。而内联函数会把我们调用这个函数的地方替换掉,所以它不需要为此生成一个内部的对象。

 // 例一、创建代码块只提供 Lollipop 或更高版本来执行
inline fun supportsLollipop(code: () -> Unit) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        code()
    }
}
// usage
supportsLollipop {
    window.setStatusBarColor(Color.BLACK)
}

5、可见性修饰符

  1、private
  2、protected:一个包成员不能被定义为 protected.
  3、internal:如果一个定义为  internal 的包成员的话,对所在的整个 module 可见。如果它是一个其他领域的成员,它就需要依赖那个领域的可见性。如有一个 private 类,那么它的 internal 修饰的函数的可见性会限制与它所在的该类的可见性。可以访问同一个 module 中的 internal 修饰的类,但不能访问其他 module的。
  4、public: 仅受限于它的领域。一个定义为 public 的成员被包含在一个 privaet 修饰的勒种,这个成员在这个类之外也是不可见的。

6、构造器

  所有构造器默认都是 public 的,它们类是可见的,可以被其他地方使用。也可以使用该语法把构造函数修改为 private:
  class C private constructor(a: Int) {...}

7、Kotlin for Android Extensions

7.1、Activities / Fragments 的 Android Extensions
  import kotlinx.android.synthetic.activity_main.*
  // 在 setContentView 被调用后就可以通过 id 名来访问 XML 中定义的 View
  import kotlinx.android.synthetic.activity_main.*
  // 可以通过 include 标签在 activity 默认布局中增加内嵌的布局。
7.2、Views Android Extensions
  import kotlinx.android.synthetic.view_item.view.*
  // 绑定一个 xml 中的 view 到另外一个 view。

8、Application 单例化和属性的 Delegated (by)

  class App : Application() {
      companion object {
          private var instance: Application? = null
          fun  instance() = instance!!
      }
      override fun onCreate() {
          super.onCreate()
          instance = this
      }
  }

我们可能需要一个属性具有一些相同的行为,使用 lazy 或 observable 可以被很有趣的实现重用,而不是一次又一次的去声明那些相同的代码。kotlin 提供了一个委托属性到一个类的方法。这就是委托属性

 class Delegate<T> : ReadWriteProperty<Any?, T> {
      fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return ...
      }
      fun setValue(thisRef: Any?,property: KProperty<*>, value: T) {...}  
      // 如果该属性是不可修改(val), 就会只有一个 getValue 函数
  }
8.1、lazy
  1、包含一个 lambda,当第一次执行 getValue 时该 lambda 会被调用,所以该属性可以被延迟初始化。之后的调用都只会返回同一个值。
  2、lazy 操作符是线程安全的。  
  3、如果不担心多线程问题或想提高更多的性能,可以使用 lazy(LazyThreadSafeMode.NONE) { ... }
  4、一般 lazy 委托的代码块可以阻止在多个不同的线程中创建多个对象。
class App : Application() {
   val database: SQLiteOpenHelper by lazy {
       MyDatabaseHelper(applicationContext)
    }
    override fun onCreate() {
      super.onCreate()
      val db = database.writeableDatabase
    }
}
8.2、Observable
  1、该委托可以检测希望观察的属性变化。当被观察属性的 set 方法被调用时,它就会自动执行我们指定的 lambda 表达式。所以一旦该属性被赋予了新值,则可以收到被委托的属性、旧值和新值。
class ViewModel(val db: MyDatabase) {
  var myProperty by Delegates.observable("") {
    d,old,new ->
    db.saveChanges(this,new)
  }
}
8.3、Vetoable
1、一个特殊的 observable, 可以来决定是否保存这个值。在真正保存之前进行一些条件判断。
var positiveNumber = Delegates.vetoable(0) {
    d, old, new -> 
    new >= 0
}
// 上面这个委托只允许在新的值是正数时执行保存。在 lambda 中,最后一行表示返回值。不需要使用 return 关键字(实质上不能被编译)
8.4、Not Null
  1、场景1:需要在某些地方初始化该属性,但不能在构造函数中确定,或不能在构造函数中做任何事。
  2、场景2:在 Activity fragment service receivers...中,一个非抽象的属性在构造函数执行之前需要被赋值。
   3、解决方案1:使用可 null 类型并且赋值为 null,直到真正去赋值。氮素,在使用时就需要不停的进行 not null 判断。
   4、解决方案2:使用 notnull 委托。含有一个可 null 的变量并会在设置该属性时分配一个真实的值。如果该值在被获取之前没有被分配,它就会抛出一个异常。
class App : Application() {
  companion object {
    var instance: App by Delegates.notnull()
  }
   override fun onCreate() {
      super.onCreate()
      instance = this
    }
}
8.5、从 Map 中映射值
  另一种委托方式,属性的值会从一个map中获取 value,属性的名字对应这个map 中的 key。
import kotlin.properties.getValue
class Configuration(map: Map<String,Any?>) {
  val width: Int by map
  val height: Int by map
  val dp: Int by map
  val deviceName: String by map
}
// usage
conf = Configuration(mapof(
  "width" to 1080,
  "height" to 720,
  "dp" to 240,
   "deviceName" to "myDecive"
))
8.6 custom delegate
 自定义委托需要实现 ReadOonlyProperty / ReadWriteProperty 两个类,具体取决于被委托的对象是 val 还是 var
// step1
private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {
  private var value: T? = null
  override fun getValue(thisRef: Any?, property: KProperty<*>): T {
      return value ?: throw IllegalStateException("${desc.name not initialized}")
  }
  
  override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
      this.value = if (this.value == null) value else throw IllegalStateException("${desc.name} already initialized")
      }
}
// step2: usage
object DelegatesExt {
  fun notNullSingleValue<T>(): ReadWriteProperty<Any?, T> = NotNullSingleValueVar()
}
8.7 重新实现 Application 单例
class App : Application() {
    companion object {
        var instance: App by Delegates.notNull()
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}  
// 此时可以在 app 的任何地方修改这个值,因为**如果使用 Delegates.notNull(), 属性必须是 var 的。可以使用刚刚创建的委托,只能修改该值一次
companion object {
    var instance: App by DeleagesExt.notNullSingleValue()
}

9、集合和函数操作

  1、Iterable: 父类。可以遍历一系列的都是实现这个接口
  2、MutableIterable: 一个支持便利的同时可以执行删除的 Iterables
  3、Collection:
  4、MutableCollection:支持增加删除item 的 collection。提供了额外的函数,如 add、remove、clear等
  5、List: 范性有序集合。
  6、MutableList: 支持增删item 的 List
  7、Set: 无序并不支持重复 item 的 集合
  8、MutableSet: 支持增删item 的 Set
  9、 Map: 
  10、MutableMap: 支持增删 item 的 map
9.1、总数操作符

1、Any:如果至少有一个元素符合给出的判断条件,则返回 true

val list = listOf(1,2,3,4,5,6)
assertTrue(list.any { it % 2 == 0 })
assertFalse(list.any { it > 10})

2、all:如果全部的元素符合给出的判断条件,则返回 true

assertTrue(list.add { it < 10})
assertFalse(list.all { it % 2 == 0})

3、count: 返回符合给出判断条件的元素总数

assertEquals(3,list.count {it % 2 == 0})

4、fold: 在一个初始值的基础上从第一项到最后一项通过一个函数累计所有的元素

asserEquals(25, list.fold(4) { total, next -> total + next})

5、foldRight: 与 fold 一样,但顺序是从最后一项到第一项。
6、forEach: 遍历所有元素,并执行给定的操作。

list.forEach { println(it) }

7、forEachIndexed: 与 forEach ,同时可得到元素的 Index

list.forEachIndexed { index, value -> println("position $index contains a $value")}

8、max: 返回最大一项,如果没有则返回 null
9、maxBy: 根据给定的函数返回最大的一项,没有返回 null

assertEquals(1, list.maxBy { -it })

10、min
11、minBy
12、none
13、reduce:与fold一样,但没有初始值。通过一个函数从第一项到最后一项进行累计。

assertEquals(21, list.reduce {total, next -> total + next})

14、reduceRight: 顺序从最后一项到第一项
15、sumBy: 返回所有每一项通过函数转换之后的数据的总和。

9.2、过滤操作符

1、drop:返回包含去掉前 n 个元素的所有元素的列表

assertEquals(listOf(5,6), list.drop(4))

2、dropWhile: 返回根据给定函数从第一项开始去掉指定元素的列表
3、dropLastWhile:返回根据给定函数从最后一项开始去掉指定元素的列表
4、filter:过滤

assertEquals(listOf(2,4,6), list.filter{it % 2 == 0})

5、filterNot
6、filterNotNull
7、slice:过滤一个list 中指定 index 的元素
8、take: 返回从第一个开始的 n 个元素
9、takeLast: 返回从最后一个开始的 n 个元素
10、takeWhile: 返回从第一个开始符合给定函数条件的元素

9.3、映射操作符

1、flatMap:遍历所有的元素,为每一个创建一个集合,最后把所有集合放在一个集合中。
2、groupBy:返回一个根据给定函数分组后的 map
3、map:返回一个每一个元素根据给定函数转换所组成的list
4、mapIndexed:返回一个每一个元素根据给定的包含元素 index 的函数转换所组成的 list
5、mapNotNull

9.4、元素操作符

1、contains
2、elementAt:返回给定index对应的元素,如果index数组越界则会抛出 IndexOutOfBoundsException
3、elementAtOrElse: 越界则给出默认值
4、elementAtOrNull
5、first
6、firstOrNull
7、indexOf
8、indexofFirst
9、indexOfLast
10、last
11、lastIndexOf
12、lastOrNull
13、single:返回符合给定函数的单个元素,如果没有符合或超过一个,则抛出异常
14、singleOrNull

9.5、生产操作符

1、merge:把两个集合合并为一个新的,相同index的元素通过给定的函数进行合并生成新的元素作为新集合中的一个元素,返回新集合。新集合的大小由最小的那个集合大小决定
2、partition: 把一个给定集合的分割为两个,第一个集合是由原集合每一项元素匹配给定函数条件返回 true 的元素组成,第二集合为false
3、plus
4、zip:返回由 pair 组成的 list,每个 pair 由 两个集合中相同index 的元素组成。该返回的 list 大小由最小的那个集合决定。
5、unzip:从包含 pair 的 List 中生成包含List的Pair

9.6、顺序操作符

1、reverse:返回一个与指定list相反顺序的list
2、sort:返回一个自然排序后的list
3、sortBy:指定函数排序
4、sortDescending:降序
5、sortDescendingBy:指定函数降序

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

推荐阅读更多精彩内容