首页 > 解决方案 > 我应该使用 Object 还是文件级 val 创建单例?

问题描述

我们希望有一个将在整个代码库中使用的类的单个实例。我们创建了一个专用包来保存这个实例。如果我理解正确的话,有两种方法可以声明单例。

(示例使用Jackson,但这并不是以任何方式特定的。)

目的

package net.goout.jackson

import com.fasterxml.jackson.databind.ObjectMapper
...

object Jackson : ObjectMapper() {
    init {
        configure(...)
    }
}

文件级val

package net.goout.jackson

import com.fasterxml.jackson.databind.ObjectMapper
...

val jackson = ObjectMapper().apply {
    configure(...)
}

在这两种情况下,只创建了一个实例,并且调用站点相同(除了命名略有不同)。

这两种方法有什么实际区别吗?

标签: kotlin

解决方案


我无法发现任何实际差异,不!

查看生成的字节码会发现这两种情况比您想象的更相似:都有一个静态初始化器和一个字段。主要区别在于,object如果它们在新类中并且字段 ( INSTANCE) 是公共的,而在这种var情况下它是私有的并且通过名为 的隐藏类中的 getter 方法访问…Kt。(实际上,无论如何,getter 通常都会得到优化。)这可能会影响初始化顺序,但这在这里无关紧要。

在语言层面,object版本会创建一个新的子类,而val版本不会——所以你可能会认为后者稍微“更纯粹”,尽管我看不出这对你有什么影响。如果你从 Java 调用,这两种情况会有不同的复杂性——尽管问题只提到了 Kotlin。

而且val版本略短且简单——只有一点点优势,但在没有任何其他因素的情况下,简洁和简单是好事!

顺便说一句,问题假设该configure()方法是“流利的”,即返回调用它的对象。但即使没有,您也可以通过简单地将其包围在apply()调用中来获得相同的效果。


推荐阅读