Kotlin 变量声明与对象初始化

一、变量声明:val / var

1. 核心区分

关键字 含义 可否重新赋值 对应Java
val 只读变量(不可变引用 ❌ 不能重新赋值(引用不变,对象内部属性可修改) final 变量
var 可变变量(可变引用 ✅ 支持重新赋值 普通非final变量

2. 语法格式

// 方式1:类型自动推导(推荐)
val name = "Kotlin"
var age = 20

// 方式2:显式声明类型,冒号分隔
val name: String = "Kotlin"
var age: Int = 20

// ❌ 错误:声明变量不赋值且不指定类型,无法推导
// val a
// ✅ 声明不立即赋值,必须显式标注类型
val a: Int
a = 10

编码规范:优先使用 val,只有需要修改时才用 var

3. 易错点:val ≠ 对象不可变

class Person(var name: String)

fun main() {
    val p = Person("Tom")
    p.name = "Jack" // ✅ 允许!val只是引用不能变,对象内部可变
    // p = Person("Lisa") ❌ 禁止重新赋值引用
}

二、延迟初始化 / 懒初始化

1. lateinit var 延迟初始化(只能 var,非空、不能基础类型Int/String

适用场景:变量声明时无法赋值,后续一定会初始化,避免空安全 ?

lateinit var text: String

fun init() {
    text = "hello"
}

// 判断是否完成初始化
if(::text.isInitialized){
    println(text)
}

限制:

  • 不能用于 val
  • 不支持基础数据类型(Int、Boolean等)
  • 不能赋值为 null

2. by lazy 懒加载(只能 val,首次访问才执行初始化

线程安全默认同步,适合开销大的对象

val data: String by lazy {
    println("执行初始化")
    "加载完成"
}

fun main() {
    println("start")
    println(data) // 首次访问执行lambda
    println(data) // 直接返回缓存值,不再执行
}

三种模式:

// 默认:SYNCHRONIZED 多线程单例
val v1 by lazy { ... }
// PUBLICATION 多线程允许多次创建,返回最先完成的值
val v2 by lazy(LazyThreadSafetyMode.PUBLICATION){...}
// NONE 不加同步,单线程环境使用,性能最高
val v3 by lazy(LazyThreadSafetyMode.NONE){...}

对比记忆

  • lateinit var:随时手动赋值;var、运行时赋值、无法缓存
  • by lazy:首次读取自动初始化;val、懒加载、自带缓存

三、空安全相关变量

var str: String? = null // 可空类型,必须加 ?
str = "test"

// 安全调用
str?.length
// 非空断言(慎用,空时抛异常)
str!!.length

四、对象初始化(类实例创建)

1. 基础构造器创建对象

Kotlin 不需要 new 关键字

class Person(name: String) // 主构造函数

// 对象实例化
val p = Person("张三")

2. 主构造函数 + 属性简写(高频写法)

直接在构造器声明属性,省去单独赋值

// name只读,age可变
class User(val name: String, var age: Int)

val u = User("李四", 22)
println(u.name)
u.age = 23

3. 初始化块 init{}

主构造函数执行时同步执行,多个 init 按顺序执行

class User(val name: String) {
    init {
        println("初始化块执行,name=$name")
    }
}

4. 次构造函数 constructor

class User(val name: String) {
    constructor() : this("默认名称"){
        // 次构造逻辑
    }
}
val u = User()

5. 匿名对象(Object)

// 单次使用匿名对象
val obj = object {
    val msg = "匿名对象"
}
println(obj.msg)

// 继承场景
val runnable = object : Runnable {
    override fun run() {}
}

五、常见初始化模式汇总示例

class Student(val id: Int) {
    // 普通立即初始化
    val school = "大学"
    var score = 0

    // 懒加载
    val info: String by lazy { "学生ID:$id" }

    // 延迟初始化
    lateinit var address: String

    init {
        println("Student 初始化块 id=$id")
    }
}

fun main() {
    val s = Student(1001)
    s.address = "深圳"
    println(s.info)
}

六、面试高频区分小结

  1. val:引用不可变;var:引用可变
  2. lateinit var:运行时手动赋值,不支持基础类型、val
  3. by lazy:读取时初始化,val专用,缓存结果
  4. 对象创建无 new;主构造参数添加 val/var 自动成为类成员
  5. init{} 在主构造调用阶段执行,早于次构造函数
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容