object 用于创建单例模式
实例:
object Resource {
val name = "Name"
}
lazy 懒属性(延迟加载)
实例:
val p: String by lazy {
// 生成string的值
}
when 用于判断 相当于java中的switch()语句
实例:
when(color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
try{…}catch(){…} 用于捕捉异常
实例
fun test() {
val result = try {
count()
}catch (e: ArithmeticException) {
throw IllegaStateException(e)
}
//处理 result
}
let 默认当前这个对象作为闭包的it参数,返回值是函数里面最后一行,或者指定return
实例:
fun testLet(): Int {
// fun <T, R> T.let(f: (T) -> R): R { f(this)}
"testLet".let {
println(it)
println(it)
println(it)
return 1
}
}
//运行结果
//testLet
//testLet
//testLet
apply 调用某对象的apply函数,在函数范围内,可以任意调用该对象的任意方法,并返回该对象
实例:
fun testApply() {
// fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
ArrayList<String>().apply {
add("testApply")
add("testApply")
add("testApply")
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = [testApply, testApply, testApply]
// [testApply, testApply, testApply]
with函数是一个单独的函数,并不是Kotlin中的extension,所以调用方式有点不一样,返回是最后一行,然后可以直接调用对象的方法,感觉像是let和apply的结合。
实例:
fun testWith() {
// fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
with(ArrayList<String>()) {
add("testWith")
add("testWith")
add("testWith")
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = [testWith, testWith, testWith]
// kotlin.Unit
函数名 | 定义 | 参数 | 返回值 | extension |
---|---|---|---|---|
let | fun T.let(f: (T) -> R): R = f(this) | it | 闭包返回 | 是 |
apply | fun T.apply(f: T.() -> Unit): T { f(); return this } | 无,可以使用this | this | 是 |
with | fun with(receiver: T, f: T.() -> R): R = receiver.f() | 无,可以使用this | 闭包返回 | 否 |
run | fun T.run(f: T.() -> R): R = f() | 无,可以使用this | 闭包返回 | 是 |
constructor 用于标识构造函数
class Customer(name: String){
init {
logger,info("Customer initialized with value ${name}")
}
}
- 二级构造函数
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
open open 注解与java 中的 final相反:它允许别的类继承这个类。默认情形下,kotlin 中所有的类都是 final ,用来表示他可以被集成
- 修饰类: 说明可以被继承
实例:
open class Base(p: Int)
class Derived(p: Int) : Base(p)
- 修饰成员 : 在 kotlin 中坚持做明确的事。不像 java ,kotlin 需要把可以复写的成员都明确注解出来,并且重写它们
open class Base {
open fun v() {}
fun nv() {}
}
class Derived() : Base() {
override fun v() {}
}
abstract 抽象类 一个类或一些成员可能被声明成 abstract 。一个抽象方法在它的类中没有实现方法。记住我们不用给一个抽象类或函数添加 open 注解,它默认是带着的。
open class Base {
open fun f() {}
}
abstract class Derived : Base() {
override abstract fun f()
}
companion object 伴随对象
在 kotlin 中不像 java 或者 C# 它没有静态方法。在大多数情形下,我们建议只用包级别的函数。如果你要写一个没有实例类就可以调用的方法,但需要访问到类内部(比如说一个工厂方法),你可以把它写成它所在类的一个成员(you can write it as a member of an object declaration inside that class)更高效的方法是,你可以在你的类中声明一个伴随对象,这样你就可以像 java/c# 那样把它当做静态方法调用,只需要它的类名做一个识别就好了
实例:获取全局的Application实例
companion object {
lateinit var instance: App
}
sealed 密封类
密封类用于代表严格的类结构,值只能是有限集合中的某中类型,不可以是任何其它类型。这就相当于一个枚举类的扩展:枚举值集合的类型是严格限制的,但每个枚举常量只有一个实例,而密封类的子类可以有包含不同状态的多个实例。
声明密封类需要在 class 前加一个 sealed 修饰符。密封类可以有子类但必须全部嵌套在密封类声明内部.
sealed class Expr {
class Const(val number: Double) : Expr()
class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
注意密封类子类的扩展可以在任何地方,不必在密封类声明内部进行。
使用密封类的最主要的的好处体现在你使用 when 表达式。可以确保声明可以覆盖到所有的情形,不需要再使用 else 情形。
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
lateinit 延迟初始化属性
通常,那些被定义为拥有非空类型的属性,都需要在构造器中初始化.但有时候这并没有那么方便.例如在单元测试中,属性应该通过依赖注入进行初始化, 或者通过一个 setup 方法进行初始化.在这种条件下,你不能在构造器中提供一个非空的初始化语句,但是你仍然希望在访问这个属性的时候,避免非空检查.
为了处理这种情况,你可以为这个属性加上 lateinit 修饰符
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method()
}
}
这个修饰符只能够被用在类的 var 类型的可变属性定义中,不能用在构造方法中.并且属性不能有自定义的 getter 和 setter访问器.这个属性的类型必须是非空的,同样也不能为一个基本类型.
在一个延迟初始化的属性初始化前访问他,会导致一个特定异常,告诉你访问的时候值还没有初始化.