首页 > 其他分享 >Kotlin中的lateinit、lazy

Kotlin中的lateinit、lazy

时间:2023-05-26 12:44:16浏览次数:28  
标签:初始化 lazy 变量 Kotlin String lateinit public name

lateinit

lateinit 关键字用来修饰一个类的非空成员变量,表示该成员变量的值在稍后合适的时机会初始化,例如:

class Test {
	lateinit var name: String
	
	fun test() {
		if (::name.isInitialized) {
			println("name is initialized")
		}
		println(name)
	}
}

在给 lateinit 修饰的成员变量赋值之前如果有代码试图访问该成员变量的值,则会直接抛出异常。在访问 lateinit 修饰的成员变量之前可以先用 isInitialized 来判断该成员变量是否已经赋值了。

上述代码转成字节码之后再反编译后如下:

public final class Test {
   public String name;

   @NotNull
   public final String getName() {
      String var10000 = this.name;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("name");
      }

      return var10000;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }

   public final void test() {
      String var1;
      if (((Test)this).name != null) {
         var1 = "name is initialized";
         System.out.println(var1);
      }

      String var10000 = this.name;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("name");
      }

      var1 = var10000;
      System.out.println(var1);
   }
}

从上述代码可以看出,编译器会为 lateinit 修饰的成员变量name生成get方法和set方法,在调用get方法的时候会判断变量是否已经初始化,若未初始化则会抛出 UninitializedPropertyAccessException

isInitializedkotlin.reflect.KProperty0的一个扩展属性,可以用于判断某个成员变量是否已经初始化。

lazy

lazy 用于延迟初始化一个成员变量到其首次被访问的时候,且该成员变量只会被初始化一次,例如:

class Test {

    val name: String by lazy {
        "william"
    }
	
    fun test() {
        println(name)
    }
}

lazy 需要配合by关键字来使用,表示将 name 的初始化由lazy代理完成。因为只会被初始化一次,所以 lazy 只能用于 val 修饰的成员变量。

lazy 是一个高阶函数,其具体实现在LazyJVM.kt中:


public interface Lazy<out T> {
    /**
     * Gets the lazily initialized value of the current Lazy instance.
     * Once the value was initialized it must not change during the rest of lifetime of this Lazy instance.
     */
    public val value: T

    /**
     * Returns `true` if a value for this Lazy instance has been already initialized, and `false` otherwise.
     * Once this function has returned `true` it stays `true` for the rest of lifetime of this Lazy instance.
     */
    public fun isInitialized(): Boolean
}

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

其接受一个初始化函数作为参数,返回一个SynchronizedLazyImpl对象,该对象实现了Lazy接口。SynchronizedLazyImpl 从其名字上就可以看出它使用synchronized关键字确保了其初始化变量的过程是线程安全的。

如果我们能够确认成员变量的初始化一定是线程安全的,那么可以使用另一个lazy方法来指定LazyThreadSafeMode,如下所示:

public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
    when (mode) {
        LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
        LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
        LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
    }
	
class Test {

    val name: String by lazy (LazyThreadSafeMode.NONE) {
        "william"
    }
	
    fun test() {
        println(name)
    }
}

查看SafePublicationLazyImpl的实现可以发现其为成员变量加了Volatile关键字修饰,可以保证可见性。而UnsafeLazyImpl的实现则没有任何同步措施,需要确保每次访问成员变量都是在同一个线程。

标签:初始化,lazy,变量,Kotlin,String,lateinit,public,name
From: https://www.cnblogs.com/jqctop1/p/17432544.html

相关文章

  • Kotlin学习 02
    在前一次只能选择省份简称的基础上,增加了输入车牌号码的交互这次主要是自己动手写代码实现:1、动态生成7位的车牌输入框EditText2、省份是选择的,车牌号是手动输入的3、点击清除实现了最后一位的删除,并自动将焦点移动到前面框中自己实现一些功能之后,确实发现kotlin能剩下很多......
  • 【客户端学习】Kotlin 协程的基本概念及用法
    协程是什么?协程是一种编程思想,并不局限于特定的语言。除Kotlin以外,其他的一些语言,如Go、Python等都可以在语言层面上实现协程。KotlinCoroutine本质上是Kotlin官方提供的一套线程封装API,其设计初衷是为了解决并发问题,让「协作式多任务」实现起来更方便。协程与线程的......
  • Kotlin中的无符号数据类型
    无符号数据类型Kotlin支持了几种常见的无符号整型,如下表所示:数据类型数据大小取值范围UByte1字节0~255UShort2字节0~65535UInt4字节0~2^32-1ULong8字节0~2^64-1除此之外,还支持了对应无符号整型的数组类型:UByteArrayUShortArrayUIntAr......
  • Kotlin学习 01
    之前因为工作没有转型kotlin的必要,并且一些杂事较多,一直没有好好深入学习kotlin。现在放眼看去,kotlin已经是统治地位了,不会kotlin,真不好意思说自己会做安卓开发。非常遗憾,现在重新开始,我任是一个爱学新技术的追风少年。我的学习方法是:看语法讲解看代码修改代码或者自己实现......
  • From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
    FromJavaToKotlin,空安全、扩展、函数、Lambda概述(Summarize)• Kotlin是什么?• 可以做什么?• Android官方开发语言从Java变为Kotlin,Java有哪些问题?• Kotlin的优点• Kotlin特性(Features)Kotlin是什么?Kotlin出自于捷克一家软件研发公司 JetB......
  • Duplicate class androidx.lifecycle.ViewModelLazy found in modules lifecycle-view
    AS版本:AndroidStudioBumblebee|2021.1.1Patch1Build#AI-211.7628.21.2111.8139111,builtonFebruary2,2022Runtimeversion:11.0.11+9-b60-7590822amd64VM:OpenJDK64-BitServerVMbyOracleCorporationWindows1010.0GC:G1YoungGeneration,G1OldGene......
  • Kotlin基本语法
    数据的类型和C++都差不多。大小都一样重点:KolIN的基本类型可以像对象一样调用方法i.TOBytY.plus(4)字符串模板${}花括号里可以是一个表达式 不可变类型val==const条件语句中的区间 in1..100rangeto有点像Python中的in。。索引方法区间打印的魔法列表和......
  • 记一个 Duplicate class kotlin-stblib vs kotlin-stdlib-jdk7/8 编译问题引发的案例
    某天将项目kotlin版本升级到了1.8.0,然后编译报错了,Duplicateclasskotlin-stblibvskotlin-stdlib-jdk7/8然后开始寻求解决方案...Duplicateclasskotlin-stblibvskotlin-stdlib-jdk7/8kotlin-stdlibkotlin1.8.0基于JVM1.8编译,不再支持JVM1.6和1.7。后续不......
  • Kotlin源码分析
    Compiler目录clisrc下面的是命令行下的编译入口,包括了jvm,重点是K2JVMCompiler执行编译过程和命令行接口CLITool|--CLICompiler|--K2JSCompiler|--K2JsIrComiler|--K2JVMCompiler|--K2MetadataCompilerCLITool|--doMain|--exec|--execImpl|--createArgument|--parseA......
  • 当我再次用Kotlin完成五年前已经通过Kotlin完成的项目后
     >近日来对Kotlin的使用频率越来越高,也对自己近年来写过的Kotlin代码尝试进行一个简单的整理.翻到了自己五年前第一次使用Kotlin来完成的一个项目([贝塞尔曲线](https://juejin.cn/post/6844903556173004807)),一时兴起,又用发展到现在的Kotlin和Compose再次完成了这个项......