Kotlin 延迟初始化(Lazy Initialization)
定义
在 Kotlin 中,延迟初始化允许你延迟一个对象的初始化,直到首次访问该对象时才进行初始化。这通常用于那些初始化开销较大,或者只在程序运行的某个特定点才需要的对象。Kotlin 提供了 lazy
委托属性来实现延迟初始化。
使用
要使用 lazy
进行延迟初始化,你需要将 lazy
委托用于一个 val
属性,并且提供一个 lambda 表达式来初始化该值。这个 lambda 表达式只会在第一次访问该属性时被调用。
下面是一个示例:
import kotlin.lazy | |
class MyClass { | |
// 使用 lazy 进行延迟初始化 | |
val lazyValue: String by lazy { | |
println("Initializing lazyValue") | |
"This is the value" | |
} | |
fun useLazyValue() { | |
println(lazyValue) | |
} | |
} | |
fun main() { | |
val myClass = MyClass() | |
myClass.useLazyValue() // 输出 "Initializing lazyValue" 和 "This is the value" | |
myClass.useLazyValue() // 只输出 "This is the value",因为 lazyValue 已经被初始化了 | |
} |
在上面的例子中,lazyValue
属性使用了 lazy
委托,并且提供了一个 lambda 表达式来初始化它。当我们第一次调用 useLazyValue()
方法时,lazyValue
会被初始化,并且打印出 "Initializing lazyValue"。当我们再次调用 useLazyValue()
时,因为 lazyValue
已经被初始化了,所以不会再次执行 lambda 表达式,只会打印出 "This is the value"。
线程安全
默认情况下,lazy
是线程安全的,它会确保在多线程环境中只初始化一次。但是,如果你确定你的代码将在单线程环境中运行,并且想要提高性能,你可以使用 LazyThreadSafetyMode.NONE
参数来创建一个非线程安全的延迟初始化属性。
Kotlin 密封类(Sealed Classes)
定义
密封类是一种特殊的类,用于表示受限的类继承结构:当一个值可以是有限集合中的几种类型之一时,你可以使用密封类来表示它。在密封类的子类中,所有的子类都必须在相同的文件中声明。
使用
使用密封类可以帮助你优化代码,特别是在处理有限集合的类型时。通过使用密封类,你可以确保不会有其他未声明的子类存在,这有助于保持代码的清晰性和可维护性。
下面是一个示例:
sealed class Expression { | |
class Constant(val number: Double) : Expression() | |
class Sum(val e1: Expression, val e2: Expression) : Expression() | |
// 其他可能的子类... | |
// 示例:评估表达式 | |
fun evaluate(): Double = when (this) { | |
is Constant -> number | |
is Sum -> e1.evaluate() + e2.evaluate() | |
// 处理其他可能的子类... | |
else -> throw IllegalArgumentException("Unknown expression") | |
} | |
} | |
fun main() { | |
val sum = Expression.Sum(Expression.Constant(1.0), Expression.Constant(2.0)) | |
println(sum.evaluate()) // 输出 3.0 | |
} |
在上面的例子中,我们定义了一个 Expression
密封类,它有两个子类:Constant
和 Sum
。我们还定义了一个 evaluate
方法,该方法使用 when
表达式来根据表达式的类型执行不同的操作。由于 Expression
是一个密封类,所以我们可以确保 when
表达式中的 else
分支永远不会被执行(除非我们添加了新的子类但忘记了更新 when
表达式)。这有助于我们避免运行时错误,并使代码更加清晰和可维护。