wordpress文学站,网站开发硬件设计,网站域名申请,郑州制作网页的公司在笔者的Kotlin交流群里#xff0c;不少同学反复遇到了一些相似的问题。这些问题大都比较基础#xff0c;但又容易产生误解。因此#xff0c;我决定写一篇文章#xff0c;整理群里同学遇到的一些问题 变量和常量的使用 在Kotlin语言中#xff0c;我们使用var声明变量… 在笔者的Kotlin交流群里不少同学反复遇到了一些相似的问题。这些问题大都比较基础但又容易产生误解。因此我决定写一篇文章整理群里同学遇到的一些问题 变量和常量的使用 在Kotlin语言中我们使用var声明变量使用val声明常量。由于来自Java语言中没有区分常量变量的影响一些同学对这两个关键字的理解有问题。为了理解这两个变量的区别我们可以用两个等式来说明一下 var str: String abc public String str abcval str: String abc public final String str abc
复制代码符号后面是对应的Java代码Java语言使用final关键字声明常量。很明显使用明确的变量和常量声明更有助于理解。 注一些Java程序员很少使用final关键字这说明这部分同学对于常量的使用不太理解。事实上JVM中有一个常量池如果发现常量池中存在该值就直接使用反之则创建并存入常量池。从这个层面来说使用常量比使用变量效率更高。更重要的是如果你声明一个不会被改动的变量使用final修饰将更准确也更安全。 lateinit 其实在使用Kotlin语言的这两年里我从来没有用过这个关键词。但刚刚接触Kotlin语言的同学似乎很喜欢使用这个修饰符修饰变量。 这个关键词是做什么的呢这很有意思 在Kotlin语言中我们必须严格区分可选值和非可选值。而无论是可选值还是非可选值在声明的时候你都必须首先初始化。 那么如果本身是一个非可选值但在初始化的时候我们并不知道应该赋什么初始值。或者说我们压根就不想赋初始值该怎么办lateinit就是用于解决这个问题的。 其实这个场景的确广泛存在比如这个变量是一个对象类型的数据。很明显给一个对象变量赋予一个初始值的意义不大。因此你可以选择使用lateinit修饰这个变量。可是与此同时你的灾难也降临了 群里同学反馈多次的一个问题就是提示变量没有初始化。 其实本身这个问题并不难但难的是你要完全弄清楚使用lateinit的前提。如果你决定使用lateinit你至少应该记住下面两个规则 lateinit只能用于修饰非可选值。因此必须确保你的这个变量在任何时候都不会被赋值为空。lateinit表示这个变量的初始化可能发生在任何时候。因此。使用lateinit之前问一问自己。你是否非常清楚你一定会在使用这个变量之前将其进行初始化。为了避免因为未初始化引起的异常问题Kotlin语言为每一个lateini属性实例提供了一个判断是否已经初始化的属性值isInitialized。因此为了避免出现初始化问题你最好判断一下这个变量是否已经完成初始化 private lateinit var dog: Dog
if (::dog.isInitialized) {....
}
复制代码非可选值中的空指针陷阱 部分同学喜欢这样声明数据类 data class Ticket(var id: Long, var name: String ...)
复制代码对于客户端类应用数据类通常对应后台返回的一段Json字符串。那么悲剧又诞生了如果后台没有返回name字段Json框架在进行数据解析的时候认为name为空值尝试将其赋值为空。不可预料地臭名昭著的空指针异常又出现了。 因此记住一个原则除非你确定这个变量一定不会被赋值为空。否则请尽量使用可选值。 可选值中的空指针陷阱 类似地在可选值中也存在着空指针陷阱。而因为受到Java语言的影响这个部分出现空指针异常的概率更高。看下面的例子 var isRight: Boolean? nullif (isRight!!) {...
}
复制代码对于上面的代码Kotlin将毫不留情地抛给你一个空指针异常。比Java空指针异常更温柔的是这个空指针异常的名称叫做KotlinNullPointerException。 因此记住一个原则如果使用可选值需要进行解包的时候。一定要确定这个可选值此刻是有值的。针对上面这个例子更好的处理方式应该是这样 var isRight: Boolean? nullif (isRight ?: false) {...
}
复制代码不要误会我没有基本数据类型 Kotlin认为所谓的基本数据类型所谓的拆包封包是没有意义的。因此在Kotlin语言中所有的基本数据类型变量也是对象拥有与变量一样的行为。 所以记住一个原则从Java转换到Kotlin在使用基本数据类型变量的时候同样需要注意合理地选择可选值和非可选值慎用lateinit。 双冒号到底是个什么东西 双冒号::操作符是Kotlin语言特有的操作符。它主要有以下几个作用 获取KClass引用获取函数引用获取属性引用获取构造函数引用获取KClass引用 这是很常用的表达式不过通常用于获取java的Class实例 val javaClass Person::class.java
复制代码注这在Android开发中比较常用通常用于获取Activity的Java class实例。 获取函数引用 在Kotlin语言中你可以使用函数作为某个高阶函数的参数。使用双冒号操作符可以用于获取具体的函数引用作为参数传入目标函数 fun cdn(x: Int): Boolean {return x 3
}fun filter(x: Int, condition: (x: Int)-Boolean): Boolean {return condition(x)
}filter(5, ::cdn)
复制代码获取属性引用 Kotlin类中每一个成员变量对应一个Property实例使用双冒号操作符可以用于获取该属性实例。在lateinit场景中这很有用 class Dog {var name: String? null
}
// 注意这里获取的是Property实例而非属性本身
val property Dog::nameval receiver Dog()
println(property.get(receiver))
复制代码注类对象变量本身并没有isInitialized属性要判断lateinit变量是否已经完成初始化需要通过双冒号获取该变量对应的Property实例才能判断。 获取构造函数引用 双冒号操作符也可以用于获取某个对象的构造函数实例具体的用法是在类名称前面使用双冒号。看下面的例子 class Dog {var name: String? null
}val init ::Dog
val dog init()
println(dog.name)
复制代码注该构造函数实例同样可以作为参数传入某个高阶函数中。 PS双冒号操作符其实就是用于简化Kotlin反射而创造的一种操作符。 简单总结 你在日常使用Kotlin语言的过程中还有遇到其它问题吗如果有请留言告诉我 欢迎加入Kotlin交流群 如果你也喜欢Kotlin语言欢迎加入我的Kotlin交流群 329673958 一起来参与Kotlin语言的推广工作。 编程我们是认真的 关注欧阳锋工作室与欧阳锋同行