首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)

【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)

作者头像
韩曙亮
发布2023-03-27 20:07:00
发布2023-03-27 20:07:00
3.1K00
代码可运行
举报
运行总次数:0
代码可运行

文章目录

I . Kotlin 变量总结

初学 Kotlin , 对变量机制不清楚的同学们 , 看完这篇博客基本就对变量的定义和使用有清晰的认识 ;

1 . 变量定义只有四种情况 : ① 非空变量 / 可空变量 直接赋值非空初始值 ; ② 可空变量使用 ?= null 赋空值 ; ③ 非空变量 ( 引用类型 ) 使用 lateinit 修饰 ; ④ 抽象属性变量不初始化 ;

2 . !! 与 ? 修饰符 : 仅对于 可空类型 有效 , ? 高级不报错 , !! 低级报空指针异常 ;

3 . ?= 与 ?. 与 ?: 运算符 : ?= 用于声明可空类型 , ?. 用于空值校验 . ?: 用于空值替换 ;

II . Kotlin 非空变量

1 . Kotlin 变量分类 : Kotlin 中的变量分为两种 , 非空变量 和 可空变量 , 其中非空变量是困扰广大 Java 开发者的一大难题 , 因为 Java 中没有非空变量这个概念 , Kotlin 中各种 ?= , ?. , ?: , !! 等操作 , Java 中的所有变量都是可空的 ;

2 . Kotlin 变量的默认状态 : Kotlin 中变量默认是非空变量 , 默认状态下 , Kotlin 必须进行初始化 ;

3 . 非空变量 初始化 和 延迟初始化 : 非空变量只能有下面两种操作 , 抽象属性变量情况特殊另作说明 ;

① 直接初始化 : 直接赋值一个非空初始值 , 非空变量不能赋值 null , 否则编译器会报错 ;

② 延迟初始化 : 引用类型变量使用 lateinit 关键字修饰 , 延迟初始化时机 , 可以在使用前进行初始化 ; 但是如果使用前没有初始化 , 执行时会报错 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
	// 延迟初始化
    lateinit var name : String
    
    // 直接初始化
    var age : Int = 0
}

4 . 特殊情况 : 如果是非空对象是抽象类中的抽象属性 , 那么可以不进行初始化 , 但在其实现中 , 也是必须进行初始化或者延迟初始化的 ;

III . 非空变量不能赋空

1 . 非空变量 初始化时 不能赋值 null : 非空变量初始化时 , 不能为空 , 否则会报错 Property must be initialized or be abstract ;

2 . 非空变量 使用时 不能赋值 null :

① 变量赋值 null 情况 : 如果为 Kotlin 的非空变量 , 也就是默认状态下的变量 , 赋值 null , 编译器直接报错 ;

② 报错信息如下 : Null can not be a value of a non-null type Int ;

③ 报错分析 : 声明的 var age : Int = 0 变量 , 其默认是 非空类型 , 即 age 变量 , 用户调用时不能为空 , 故意赋值为空 , 系统不允许这种操作 ;

④ lateinit 不初始化情况 : 使用 lateinit 修饰的变量 , 但如果不初始化 , 那么调用肯定报错 , 但是报的是未初始化错误 ; 不初始化不是为空 , 但不能调用 ;

IV . lateinit 关键字

lateinit 关键字 使用要求 : 只能修饰 非空类型 , 并且是 引用数据类型 ;

① 只能修饰非空变量 : 不能修饰可空变量 , 否则报错信息如下 'lateinit' modifier is not allowed on properties of nullable types ;

② 只能修饰引用数据类型 : 不能修饰

8

种基本数据类型 , 否则报错 'lateinit' modifier is not allowed on properties of primitive types ;

2 . 基础数据类型非空变量 : 如果 非空变量 类型是

8

种基础数据类型 , 那么该变量必须赋值一个数值 , 其不能被 lateinit 修饰 , 只能先随意赋予一个初始值 , 一般设置 0 , False , 0F 等初始值 ;

V . lateinit 初始化判定

1 . 延迟初始化属性初始化判定 : this::name.isInitialized

2 . 判定需求 : 非空变量 由于存在 延迟初始化 , 那么在调用该变量的时候 , 该变量有可能没有进行初始化 , 需要判定该变量是否初始化 ;

3 . 本类中判定 : 延迟初始化 属性 只能在本类中使用 this::属性名称.isInitialized 进行判定 , 如果返回 true , 说明已经初始化 , 如果返回 false , 说明该属性还没有进行初始化 ;

4 . 其它类中判定 : 如果要在其它类中判定本类某个属性是否已经初始化 , 需要定义一个 public 方法 , 提供判定接口 , 如下代码示例 :

5 . 代码示例 :

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    lateinit var name : String
    var age : Int = 0

    fun isNameInitialized() : Boolean{
        println("this::name.isInitialized = ${this::name.isInitialized}")
        return this::name.isInitialized
    }
}

fun main() {
    var student = Student()
    if(student.isNameInitialized()) {
        println("name 属性已经初始化完毕")
    }else{
        println("name 属性没有进行初始化")
    }
}

执行结果 :

代码语言:javascript
代码运行次数:0
运行
复制
this::name.isInitialized = false
name 属性没有进行初始化
VI . Kotlin 可空变量

Kotlin 中的可空变量 , 与 Java 变量性质相同 , 所有的 Java 变量都是可空变量 ;

1 . 可空变量 声明 : 声明可空类型变量时 , 再其变量类型后 , 添加 ? 修饰 ; 注意不是变量名称后 , 是变量类型后 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String ?= null
    var age : Int? = null
    var height : Int ?= 0
}

2 . 可空变量初始化 :

① 必须初始化 : 可空变量也必须初始化 , 但可以初始化为 null 空值 ;

② 不能延迟初始化 : 可空类型不能使用 lateinit 关键字修饰 ;

VII . !! 与 ? 修饰符

1 . 可空类型前提 : !! 与 ? 修饰符 使用的前提是变量必须是 可空类型 , 非空类型不允许使用 !! 与 ? 修饰符 ;

2 . ? 和 !! 用法 : 放在变量后面 , 修饰变量 ; 如果变量不为空 , 没有任何区别 , 下面讨论变量为空的情况 ;

3 . ? 修饰变量 : 如果该变量为空 , 那么装作什么都没发生 , 继续向后执行 ; 下面的示例输出结果是 Student : name = null , age = 0 ;

?. 运算符 : 这种用法 , 也可以看成是 ?. 运算符 , 意思就是如果不为空 , 才获取值 , 如果为空 , 直接返回 null , 继续向后执行 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String ?= null
    var age : Int = 0
}

fun main() {
    var student = Student()
    //输出结果 : Student : name = null , age = 0
    println("Student : name = ${student.name?.length} , age = ${student.age}")
}

4 . !! 修饰变量 : 如果该变量为空 , 与 Java 一样 , 报空指针异常 , 应用崩溃 ; 报空指针错误 kotlin.KotlinNullPointerException ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String ?= null
    var age : Int = 0
}

fun main() {
    var student = Student()
    //输出结果 : Student : name = null , age = 0
    println("Student : name = ${student.name!!.length} , age = ${student.age}")
}

报错信息 : 此时报错空指针异常 ;

代码语言:javascript
代码运行次数:0
运行
复制
Exception in thread "main" kotlin.KotlinNullPointerException
	at variable.VariableKt.main(Variable.kt:10)
	at variable.VariableKt.main(Variable.kt)
VIII . ?= 与 ?. 与 ?: 运算符

1 . ?= 声明可空类型 : ? 还有一个作用是声明可空变量 , 此时 ? 修饰符必须在 变量类型之后 ; 声明可空类型后 , 可以为其正常赋值 , 也可以为变量赋空值 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String? = "Tom"
    var age : Int ?= null
}

2 . ?. 运算符 : 这种用法 , 也可以看成是 ?. 运算符 , 意思就是如果不为空 , 才获取值 , 如果为空 , 直接返回 null , 继续向后执行 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String ?= null
    var age : Int = 0
}

fun main() {
    var student = Student()
    //Student : name = null , name length = null , age = 0
    println("Student : name = ${student.name} , name length = ${student.name?.length} , age = ${student.age}")
}

控制台输出 :

代码语言:javascript
代码运行次数:0
运行
复制
Student : name = null , name length = null , age = 0

3 . ? : 运算符 : 该运算符是双目运算符 , 作用是前者如果为空 , 那么取后者的值 ;

① 与 Java 三木运算符 对比 : 在 Kotlin 中这个运算符与 Java 中不太一样 , 这也是一个双目运算符 , 中间不能有值 , Java 中该运算符是三木运算符 ;

代码语言:javascript
代码运行次数:0
运行
复制
class Student(){
    var name : String ?= null
    var age : Int = 0
}

fun main() {
    var student = Student()
    //Student : name = Tom , name length = 888 , age = 0
    println("Student : name = ${student.name?:"Tom"} , name length = ${student.name?.length?:888} , age = ${student.age?:18}")
}

② 控制台输出 :

代码语言:javascript
代码运行次数:0
运行
复制
Student : name = Tom , name length = 888 , age = 0

③ 代码分析 :

student.name?:"Tom" 代码中 , student.name 为空 , 那么取值后面的 "Tom" 字符串 , 因此打印的时候 , 打印 "Tom" 字符串 ;

student.name?.length?:888 代码分析 :

student.name 是空的 , 取值 null ;

student.name?.length 相当于 null?.length 其取值也是 null ;

那么 student.name?.length?:888 相当于 null?:888 ;

最终取值是右侧的 888 值 , 因此打印的时候打印 888 ;

IX . 抽象属性变量

1 . Kotlin 变量初始化 : Kotlin 中的变量是必须进行初始化的 , 可空变量 与 非空变量要求不一样 , 但是原则上都必须初始化 ;

① 非空变量 : 非空变量可以使用 lateinit 修饰 , 也可以直接进行非空值的初始化 , 直接赋值 null 报错 ;

② 可空变量 : 必须初始化 , 哪怕初始化为 null 也可以 ; 不能使用 延迟初始化 ;

2 . 变量不用初始化的特殊情况 : 抽象类 的 抽象属性 , 可以不进行初始化 , 但此时也不能使用 ; 该属性实现的时候 , 重写的属性必须进行初始化操作 , 与普通变量要求一样 ;

代码语言:javascript
代码运行次数:0
运行
复制
abstract class Variable(){
    //抽象类的抽象属性可以不用初始化
    abstract var age : Int
}

//抽象类的实现类必须进行初始化
class Student() : Variable(){
    override var age: Int = 0
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
    • I . Kotlin 变量总结
    • II . Kotlin 非空变量
    • III . 非空变量不能赋空
    • IV . lateinit 关键字
    • V . lateinit 初始化判定
    • VI . Kotlin 可空变量
    • VII . !! 与 ? 修饰符
    • VIII . ?= 与 ?. 与 ?: 运算符
    • IX . 抽象属性变量
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档