Kotlin通过关键字object扩展了经典单例的概念。它实现了以下模式:
object Logger { ... })。单例对象示例:
object DatabaseManager { fun connect() { /*...*/ } } DatabaseManager.connect()
对象表达式示例:
val listener = object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*...*/ } }
伴随对象示例:
class User { companion object Factory { fun create(name: String) = User() } } val user = User.create("Ivan")
细节:
伴随对象和对象声明之间有什么区别?它们的所有成员是否都可以作为静态成员访问?
答案:
object declaration — 全局单例,类、接口或外部层次的成员。companion object — 类内的特殊类型的对象声明,其成员可以像静态成员一样通过类名调用。然而,与Java不同,它们实际上是单例对象的字段。区别示例:
class A { companion object { fun foo() {} } object NestedObj { fun bar() {} } } A.foo() // OK A.NestedObj.bar() // OK,但这不是静态方法
故事
开发人员在对象声明中定义了可变状态,并在不同线程中未同步使用,未考虑到单例对象共享整个应用程序并可能导致竞争条件。
故事
在类内部声明对象而不是伴随对象时,需要使用静态方法,但必须通过实例调用,这降低了可读性并在从Java迁移时导致错误。
故事
在UI代码中,程序员每次都通过对象表达式创建新对象作为事件处理程序。他错误地认为它是单例,并且状态将保持;结果由于生命周期管理不当导致了内存泄漏。