------《Kotlin系列之特殊关键字详解》
关键字:in
in关键字在不同的场景下用处是不同的,以下列举几种情况。
检查一个值是否处于区间或集合内
val listOf = listOf(1, 2, 3, 4, 5)
if (3 in listOf){}
在for语句中,则表示迭代含义
// 遍历list中的每个元素
for(item in list){}
修饰泛型时表示泛型的下边界,in 表示逆变。相当于Java中的?extends T
如果泛型类只将泛型类型作为函数的入参(输入),那么使用in:
父类泛型对象可以赋值给子类泛型对象,用 in;
interface Consumer<in T> {
fun consume(item: T)
}
可以称之为消费者类/接口,因为它主要是用来消费(consume)指定的泛型对象。
关键字:out
修饰泛型时表示泛型的上边界,out 表示协变。相当于Java中的?super T
如果泛型类只将泛型类型作为函数的返回(输出),那么使用out:
子类泛型对象可以赋值给父类泛型对象,用 out
interface Production<out T> {
fun produce(): T
}
可以称之为生产类/接口,因为它主要是用来生产指定的泛型对象。
关键字:!in
!in是in的否定形式(就是效果跟is相反)
关键字:as
是相当于是显示类型转换(就是强制类型转换),转换成功就转换成功,转换失败会报错
var BtoA_Class = BClass() as AClass
class AClass : BClass(){
}
open class BClass{
}
关键字:as?
比as安全一点,转换成功就转换成功,转换失败会返回null
关键字:is
is运算符相当于java中的instanceof,用来判断当前类型是不是对应的类型
if (AClass() is BClass){}
关键字:!is
!is是is的否定形式(就是效果跟is相反)
关键字:lateinit
用于修饰 no-null 属性,用于指定该属性可在构造器以外的地方初始化
private lateinit var db: DataBase
关键字:companion
用于声明一个伴生对象,可以说相当于Java中的Static。
companion object {
//指定金额收费
val APPOINT = 1
}
//相当于Java中 static int APPOINT = 1
关键字:const
用于声明编译时常量,相当于java中的final。(注意定义全局成员时,要定义在类的外部)
const val GROUP = 2
//相当于java中 final int GROUP = 2
class mineActivity{
}
//所以java中的 static final int APPOINT = 1 在kotlin中表示为:
companion object {
//指定金额收费
const val APPOINT = 1
}
关键字:by
用于将接口或祖先类的实现代理给其他对象。
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
类的委托即一个类中定义的方法实际是调用另一个类的对象的方法 来实现的。
// 创建接口
interface Base {
fun print()
}// 实现此接口的被委托的类
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}// 通过关键字 by 建立委托类
class Derived(b: Base) : Base by b
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print() // 输出 10
}
属性委托
属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
val/var <属性名>: <类型> by <表达式>
by 关键字之后的表达式就是委托, 属性的 get() 方法(以及set() 方法)将被委托给这个对象的 getValue() 和 setValue() 方法
// 定义包含属性委托的类
class Example {
var p: String by Delegate()
}// 委托的类
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
}
fun main(args: Array<String>) {
val e = Example()
println(e.p) // 访问该属性,调用 getValue() 函数
e.p = "Runoob" // 调用 setValue() 函数
println(e.p)
}
//输出结果:
Example@433c675d, 这里委托了 p 属性
Example@433c675d 的 p 属性赋值为 Runoob
Example@433c675d, 这里委托了 p 属性
关键字:filed
Kotlin中可以使用filed标识符当作成员变量使用,也就是通过filed读写属性值
例子如下:
var autoInputPrice: Int? = 0
get() = field //field 代表了autoInputPrice
set(value) {
field = value //field 代表了autoInputPrice
}
关键字:typealias
通过这个关键字可以关联一个已有的类,可以理解为给类起一个别名。
typealias A = Thread
fun main(args: Array<String>) {
val a = A()
a.start()
}
关键字:vararg
用于修饰形参,表明该参数是个数可变的形参。
关键字:infix
标有infix关键字的函数可以使用中缀表示法(忽略该调用的点与圆括号)调用,中缀函数必须满足以下要求:
1. 它们必须是成员函数和扩展函数。
2. 它们必须只有一个参数。
3. 其参数不得接受可变数量的参数,而且不能有默认值。
举个例子
infix fun Int.plus(x: Int): Int =
this.plus(x)
// 可以中缀表示法调用函数
1 plus 2 //until 和 to就是中缀表示法的一种
// 等同于这样
1.plus(2)
关键字:inline
当你调用一个inline function的时候,编译器不会产生一次函数调用,而是会在每次调用时,将inline function中的代码直接嵌入到调用处。(正常的是利用引用去寻找我们要调用的函数)
inline 在一般的方法是标注,是不会起到很大作用的,inline 能带来的性能提升,往往是在参数是 lambda 的函数上。
fun meth(){
println("aaaa")
meth1()
}
inline fun meth1(){
println("bbbb")
}
//编译之后会变成
fun meth(){
println("aaaa")
println("bbbb")
}
使用inline修饰的函数还有一个好处是可以使用reified来修饰函数的泛型,让函数的泛型具体化。
关键字:reified
传统的泛型是会在程序运行的过程中进行擦除操作,而使用reified修饰的泛型,通过反编译二进制表现就是将泛型替换成具体的类型,不进行类型擦除。
关键字:internal
用于表示被修饰的声明只能在当前模块内可见
关键字:noinline
用于禁止内联函数中个别 Lambda 表达式被内联化
关键字:suspend
用于标识一个函数后 Lambda 表达式可作为暂停。