Kotlin -> lateinit 和 lazy 详解

lateinitlazy 详解

核心区别

特性lateinitlazy
类型可变属性修饰符 var不可变属性委托 val
初始化时机手动显式初始化,随时可变首次访问时自动初始化,之后不可变
空安全非空类型,但初始值可缺失非空类型,保证有值
适用类型不能用于基本类型(Int, Boolean等)可用于任何类型
线程安全不保证线程安全默认线程安全SYNCHRONIZED模式
检查机制使用前需确保已初始化,否则抛异常自动处理初始化,不会抛出未初始化异常

lateinit 核心用法

// 声明
class User {
    lateinit var name: String
    
    fun initialize() {
        name = "John" // 手动初始化
    }
    
    fun greet() {
        if (::name.isInitialized) { // 检查是否已初始化
            println("Hello, $name")
        }
    }
}

最佳使用场景:

  • 依赖注入
  • Activity/Fragment中的视图绑定
  • 单元测试的setUp方法中
  • 需要推迟初始化但之后可能需要修改的属性

lazy 核心用法

// 基本用法
class User {
    val name: String by lazy { 
        println("Computing name...")
        "John" // 计算并返回初始值
    }
}

// 指定线程安全模式
val expensiveData: List<Data> by lazy(LazyThreadSafetyMode.PUBLICATION) {
    loadDataFromDatabase()
}

线程安全模式:

  • SYNCHRONIZED:默认模式,线程安全,只执行一次初始化
  • PUBLICATION:多线程可能执行多次,但只有第一个结果被使用
  • NONE:不保证线程安全,适用于单线程环境,性能最好

最佳使用场景:

  • 计算开销大的属性
  • 需要根据条件计算的只读属性
  • 单例模式实现
  • 配置项和缓存数据

核心实现原理

lateinit

  • 在字节码级别,不为属性分配默认值
  • 访问前不进行空检查
  • 使用前若未初始化,抛出UninitializedPropertyAccessException

lazy

  • 内部使用SynchronizedLazyImpl等实现类
  • 持有一个初始化器函数和一个存储结果的AtomicReference
  • 首次访问时执行初始化器并缓存结果

如何选择

  • 如果属性需要在初始化后修改,使用lateinit var
  • 如果属性是只读的且可以延迟计算,使用lazy val
  • 如果处理基本类型,只能使用lazy
  • 如果在多线程环境中,优先考虑lazy
安卓报错Duplicate class org.jetbrains.org.objectweb.asm.util.CheckSignatureAdapter$State found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Printer found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Textifiable found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Textifier found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceAnnotationVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceClassVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceFieldVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceModuleVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceSignatureVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10)
04-01
<think>嗯,用户遇到了安卓项目中的重复类错误,涉及多个org.jetbrains.org.objectweb.asm.util下的类。首先,我需要理解这个问题的根本原因。错误信息显示,kotlin-compiler-embeddablekotlin-gradle-plugin这两个依赖包含了相同的类,导致冲突。这可能是因为这两个库都依赖了不同版本的ASM库,或者它们内部打包了相同类但不同版本。 接下来,我应该考虑常见的解决方法。通常,这类问题可以通过排除重复的依赖来解决。用户需要在构建文件中检查这两个模块的依赖关系,找出哪个模块引入了冲突的ASM类,然后排除掉其中一个。不过,用户提到这两个模块都是来自Kotlin的1.4.10版本,可能这时候需要确认Kotlin插件Gradle版本是否兼容,或者是否需要升级到更高版本,因为旧版本可能存在已知的依赖冲突问题。 另外,可能需要检查项目中的其他依赖是否间接引入了不同版本的ASM库。使用Gradle的依赖树分析工具(如./gradlew app:dependencies)可以帮助识别冲突的来源。如果发现有多个版本的ASM,可以强制指定使用某个版本,或者排除其他版本。 还有可能是Gradle插件本身的问题,尤其是在使用旧版本的Kotlin插件时。查看官方文档或问题追踪系统,看看是否有相关的问题解决方案。例如,升级到Kotlin 1.5或更高版本可能已经修复了这个问题,因为JetBrains可能在后续版本中调整了依赖管理。 用户还需要确认项目的Gradle配置是否正确,比如是否在多个地方重复声明了Kotlin插件,或者是否有第三方库强制覆盖了ASM的版本。有时候,插件之间的兼容性问题也会导致此类错误,需要逐一排查。 最后,如果排除依赖或升级版本无效,可能需要更深入分析依赖树,或者寻求社区官方支持。提供详细的错误日志构建文件配置会有助于更准确地定位问题。</think>这个错误是由于项目中存在重复的类定义导致的,具体涉及两个Kotlin相关模块中的ASM工具类冲突。以下是逐步分析解决方案: **根本原因分析** 1. 冲突模块:`kotlin-compiler-embeddable``kotlin-gradle-plugin`都包含`org.jetbrains.org.objectweb.asm.util`包下的同名类 2. 典型触发场景:当使用较旧版本的Kotlin插件(如1.4.x)时,其内部依赖的ASM库存在重复打包 **解决方案步骤** 1. **统一Kotlin版本** ```gradle // 在项目根build.gradle中确保所有Kotlin组件版本一致 buildscript { ext.kotlin_version = '1.8.22' // 推荐使用1.7.20+ dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } ``` 2. **排除重复依赖** ```gradle // 在app模块的build.gradle中添加排除规则 configurations { all*.exclude group: 'org.jetbrains.org.objectweb.asm', module: 'asm-util' all*.exclude group: 'org.jetbrains', module: 'kotlin-compiler-embeddable' } ``` 3. **强制使用统一ASM版本** ```gradle // 在项目根build.gradle中添加全局约束 configurations.all { resolutionStrategy { force 'org.ow2.asm:asm:9.4' force 'org.ow2.asm:asm-util:9.4' } } ``` 4. **清理构建缓存** ```bash ./gradlew cleanBuildCache ./gradlew --stop rm -rf $HOME/.gradle/caches/ ``` **验证方法** 1. 查看依赖树: ```bash ./gradlew :app:dependencies --configuration runtimeClasspath ``` 2. 确认输出中不再出现`Duplicate classes`警告 **升级建议** - 若项目允许,建议升级到Kotlin 1.8.x+,该问题在较新版本中已通过优化依赖管理得到解决 - 检查Android Gradle Plugin版本是否与Kotlin版本兼容(参考官方兼容性文档) **技术背景** 该问题源于Kotlin编译器内部使用的ASM库(Java字节码操作框架)在多个子模块中的重复打包。在构建时,Gradle的依赖解析器会发现同一类的多个实例,违反JVM的类唯一性原则。通过依赖排除版本强制可以确保类加载器只获取单一版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值