Java では、二重チェックロックと volatile を使用して、スレッドセーフなシングルトンを記述できます。
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance(String arg) {
Singleton localInstance = instance;
if (localInstance == null) {
synchronized (Singleton.class) {
localInstance = instance;
if (localInstance == null) {
instance = localInstance = new Singleton(arg);
}
}
}
return localInstance;
}
}
Kotlin ではどのように記述すればよいでしょうか?
オブジェクトについて
object A {
object B {}
object C {}
init {
C.hashCode()
}
}
私はKotlinデコンパイラを使ってそれを手に入れました
public final class A {
public static final A INSTANCE;
private A() {
INSTANCE = (A)this;
A.C.INSTANCE.hashCode();
}
static {
new A();
}
public static final class B {
public static final A.B INSTANCE;
private B() {
INSTANCE = (A.B)this;
}
static {
new A.B();
}
}
public static final class C {
public static final A.C INSTANCE;
private C() {
INSTANCE = (A.C)this;
}
static {
new A.C();
}
}
}
すべてのオブジェクトはstatic
ブロック内でコンストラクタを呼び出します。これに基づいて、これは遅延ではないと考えることができます。
正解に近いです。
class Singleton {
companion object {
val instance: Singleton by lazy(LazyThreadSafetyMode.PUBLICATION) { Singleton() }
}
}
逆コンパイル:
public static final class Companion {
// $FF: synthetic field
private static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Singleton.Companion.class), "instance", "getInstance()Lru/example/project/tech/Singleton;"))};
@NotNull
public final Singleton getInstance() {
Lazy var1 = Singleton.instance$delegate;
KProperty var3 = $$delegatedProperties[0];
return (Singleton)var1.getValue();
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
将来、Kotlin 開発者が非リフレクション実装を行うことを期待しています...
ベストアンサー1
KotlinにはJavaコードと同等のコードがありますが、より安全です。ダブルロックチェック推奨されませんJavaでもJavaでは、静的な内部クラスこれはまた、オンデマンド初期化ホルダーイディオム。
しかし、それは Java です。Kotlinでは、オブジェクトを使用するだけです(オプションで遅延デリゲート):
object Singletons {
val something: OfMyType by lazy() { ... }
val somethingLazyButLessSo: OtherType = OtherType()
val moreLazies: FancyType by lazy() { ... }
}
その後、任意のメンバー変数にアクセスできるようになります。
// Singletons is lazy instantiated now, then something is lazy instantiated after.
val thing = Singletons.something // This is Doubly Lazy!
// this one is already loaded due to previous line
val eager = Singletons.somethingLazyButLessSo
// and Singletons.moreLazies isn't loaded yet until first access...
Kotlin は、Java のシングルトンに関する人々の混乱を意図的に回避します。また、このパターンの「間違ったバージョン」 (多数存在します) を回避します。代わりに、よりシンプルで安全な形式のシングルトンを提供します。
の使用を考えるとlazy()
、他のメンバーがある場合、それぞれが個別に遅延されます。また、それらは に渡されるラムダで初期化されるため、lazy()
コンストラクターのカスタマイズについて、および各メンバー プロパティについて質問していたことを行うことができます。
その結果、Singletons
オブジェクトの遅延読み込みが発生します(インスタンスへの最初のアクセス時)、そしてsomething
(メンバーの初回アクセス時)、およびオブジェクト構築における完全な柔軟性を備えています。
参照:
ちなみに、依存性注入に似た、注入オプションを備えたシングルトンを提供する Kotlin のオブジェクト レジストリ タイプ ライブラリを調べてください。