Kotlinの遅延属性(lazy properties)

2173 ワード

Kotlinに属する委任属性この章の標準委任
遅延属性Lazylazy()は、lambdaを受け入れ、Lazy のインスタンスを返す関数であり、返されるインスタンスは、遅延属性を実装する依頼として使用することができる.すなわち、1回目の呼び出しget()は、lazy()に渡されたlambda式を実行して結果を記録し、後続の呼び出しget()は記録の結果を返すだけである.
ここで注意しなければならないのはget()メソッドを呼び出しているので、setとは関係ありません.
val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

fun main(args: Array) {
    println(lazyValue)
    println(lazyValue)
}

出力結果は
computed!
Hello
Hello

同期ロックモード
スレッドの同時初期化を防止
デフォルトでは、lazyプロパティの評価値は同期ロック(synchronized):この値は1つのスレッドでのみ計算され、すべてのスレッドで同じ値が表示されます.初期化依頼の同期ロックが必要でない場合、複数のスレッドが同時に実行できるようにすると、LazyThreadSafetyMode.PUBLICATIONがパラメータとしてlazy()関数に渡される.初期化が常に単一のスレッドで発生すると判断した場合は、LazyThreadSafetyMode.NONEモードを使用して、スレッドのセキュリティの保証や関連するオーバーヘッドはありません.
遅延属性Lazyとlateinitの違い
以下はlateinit varとby lazy{...}委任属性間の有意差:
  • lazy { ... }valのプロパティにのみ使用できることを表し、lateinitvarにのみ使用できます.finalフィールドにコンパイルできないため、不変性を保証できません.
  • lateinit varは、値を格納するバックアップフィールド(backing field)を有し、by lazy { ... }は、計算された値を1回格納し、プロキシインスタンスへの参照をクラスオブジェクトに格納し、委任インスタンスとともに使用される属性のgetterを生成する委任オブジェクトを作成する.
  • valを除いて、lateinitはnullが初期化されていない値に使用されるため、空の属性およびJava原語タイプに使用できません.クラスに存在するサポートフィールドが必要な場合はlateinitを使用します.lateinit varは、オブジェクトが見られる任意の場所から初期化することができる.1つのフレームワークコードの内部から、複数の初期化スキームは、可能な単一クラスの異なるオブジェクトである.by lazy { ... }は、逆に属性の一意の初期化器を定義し、サブクラスの属性を上書きすることによってのみ変更できます.プロパティを事前に不明な方法で外部から初期化する場合は、lateinitを使用します.
  • また、Delegatesには言及していない方法もあります.notNull()は、Javaの元のタイプのプロパティを含むnon-nullプロパティの遅延初期化に適しています.

  • 遅延属性Lazyとlateinitの使用概要lateinit外部初期化:呼び出しメソッドを使用して外部資料を初期化する必要がある場合.たとえば、次のように呼び出します.
    private lateinit var value: MyClass
    
    fun init(externalProperties: Any) {
       value = somethingThatDependsOn(externalProperties)
    }
    

    一方、lazyは、オブジェクト内部の依存関係のみを使用する場合に使用される.うん.静的変数の初期化はこの方式に適している.