我想知道创建单例类的方法,以便每个应用程序的Util类仅实例化一次。但是,当我将Java类转换为kotlin时,生成了以下代码。
这正确吗?
companion object {
private var utilProject: UtilProject? = null
val instance: UtilProject
get() {
if (utilProject == null) utilProject = UtilProject()
return utilProject!!
}
}
我可以找到一个相关的 question ,但这是带有参数的,并且我无法在没有参数的情况下进行转换。
答案 0 :(得分:18)
在Kotlin中,有一个特殊的关键字object
用于单身人士。您可以输入像这样简单的内容来使单例类正常工作:
object MySingleton
或当您需要某些成员函数时:
object MySingleton {
fun someFunction(...) {...}
}
然后使用它:
MySingleton.someFunction(...)
有一个参考文献:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
答案 1 :(得分:12)
只是
companion object {
val instance = UtilProject()
}
可以完成此任务,因为伴侣对象本身是语言级别的单例。
(在首先 调用伴随对象时将分配instance
。)
-更新-
如果需要调整何时初始化单例对象,则可以为每个类创建一个对象。
class UtilProject {
....
companion object {
val instance = UtilProject()
}
}
class AnotherClass {
...
companion object {
val instance = AnotherClass()
const val abc = "ABC"
}
}
fun main(args: Array<String>) {
val a = UtilProject.instance // UtilProject.instance will be initialized here.
val b = AnotherClass.abc // AnotherClass.instance will be initialized here because AnotherClass's companion object is instantiated.
val c = AnotherClass.instance
}
在这里,AnotherClass.instance
在实际调用AnotherClass.instance
之前被初始化。在调用AnotherClass
的伴随对象时初始化它。
为了避免在需要时进行初始化,可以这样使用:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object UtilProjectSingleton {
val instance = UtilProject()
}
object AnotherClassSingleton {
val instance = AnotherClass()
}
fun main(args: Array<String>) {
UtilProject.f()
println(AnotherClass.abc)
val a = UtilProjectSingleton.instance // UtilProjectSingleton.instance will be initialized here.
val b = AnotherClassSingleton.instance // AnotherClassSingleton.instance will be initialized here.
val c = UtilProjectSingleton.instance // c is a.
}
如果您不关心何时初始化每个单例,也可以这样使用:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object Singletons {
val utilProject = UtilProject()
val anotherClass = AnotherClass()
}
fun main(args: Array<String>) {
val a = Singletons.utilProject
val b = Singletons.anotherClass
}
总而言之,
object
或companion object
是Kotlin中的一个单例对象。
您可以在 object 或 objects 中分配变量,然后像使用单例一样使用变量。
object
或companion object
在首次使用时被实例化。
val
中的var
和object
s在首次实例化object
时(即,第一次使用object
时)被初始化。
答案 2 :(得分:2)
在Kotlin中,您应该摆脱实用程序单例类的整个概念。惯用的方法是简单地将所有声明移到顶层。
Java:
public final class Util {
public static final Util UTIL = new Util();
private int prefixLength = 4;
private Util() {}
public void setPrefixLength(int newLen) {
prefixLength = newLen;
}
public String extractVin(String input) {
return input.substring(prefixLength);
}
}
用法:
String vin = UTIL.extractVin("aoeuVN14134230430")
在Kotlin中,只需创建一个名为util.kt
的独立文件,其中包含以下内容:
var prefixLength = 4
fun String.extractVin() = this.substring(prefixLength)
用法:
val vin = "aoeuVN14134230430".extractVin()
如果您的Java直觉在这里触发了一个危险信号,只需记住 package 是命名空间构造,并且与Java相反,Kotlin不会混淆命名空间和封装的问题。没有“ package-private”访问级别,因此您无需负担必须将某些内容保留在同一包中以便可以将其设置为package-private的负担。
因此,在Java中创建退化类作为解决方法的地方,在Kotlin中,只需在其自己的包中创建文件。
答案 3 :(得分:2)
仅需要单词对象。
object UtilProject {
var bar: Int = 0
fun foo() {
}
}
您直接访问只有一个实例的对象
fun main(args: Array<String>) {
UtilProject.bar = 1
println(UtilProject.bar)
}
答案 4 :(得分:1)
超级简单的懒惰示例:
ENOSPC
答案 5 :(得分:1)
class TestMySingleton private constructor() {
companion object {
var single = TestMySingleton()
fun getInstance(): TestMySingleton {
if (single == null)
single = TestMySingleton()
return single
}
}
}
答案 6 :(得分:1)
带参数的变体
open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null
fun getInstance(arg: A): T {
val checkInstance = instance
if (checkInstance != null) {
return checkInstance
}
return synchronized(this) {
val checkInstanceAgain = instance
if (checkInstanceAgain != null) {
checkInstanceAgain
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
答案 7 :(得分:0)
经过翻新以支持api调用的Singleton
示例。
object RetrofitClient {
private var instance: Api? = null
private val BASE_URL = "https://jsonplaceholder.typicode.com/"
fun getInstance(): Api? {
if (instance == null) {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
instance = retrofit.create(Api::class.java)
}
return instance
}
}
答案 8 :(得分:0)
class MyClass {
init {
println("init is called")
}
companion object {
private var obj: MyClass? = null
fun getInstance(): MyClass {
if (obj == null) {
obj = MyClass()
}
return obj as MyClass
}
}
fun printHello() {
println("Hello World")
}
您可以通过MyClass.getInstance()
来创建其实例,例如java
答案 9 :(得分:0)
这会有所帮助。我正在使用 Dialog
类,但您可以使用示例了解如何实现。
class MyClass(context: Context) : Dialog(context) {
companion object {
lateinit var INSTANCE: MyClass
@JvmStatic
fun getInstance(context: Context): MyClass{
if (!::INSTANCE.isInitialized) {
INSTANCE = MyClass(context)
}
return INSTANCE
}
}}