Kevin Learn Kotlin:空指针检查
2022-02-16 本文已影响0人
Kevin_小飞象
可空类型
当我们在声明方法时,如果允许在这个方法被调用的时候传给它 null 的实参,则需要显示地 在类型名称后面加上问号来标记它:
fun learn(s: String?): Int =
问号可以加在任何类型的后面来表示这个类型的变量可以存储 null 引用,而所有常见类型默认都是非空的,除非显示地把它标记为可空。
当你有一个可空类型的值,对它的操作也会受到限制:
- 不能调用它的方法
- 不能把它赋值给非空类型的变量
- 不能把可空类型的值传给拥有非空类型参数的函数
fun learn(s: String): Int =
if (s != null) s.length else 0
判空辅助工具
1. 安全调用运算符 "?."
处理可空对象
安全调用运算符 ?. 把一次 null 检查和一次方法调用合并成一个操作。
fun main() {
printAllCaps("Kevin")
printAllCaps(null)
}
fun printAllCaps(s: String?) {
val allCaps: String? = s?.toUpperCase()
println(allCaps)
}
运行结果:
KEVIN
null
处理可空属性
安全调用不光可以调用方法,也能访问属性:
class Employee(val name: String, val manager:Employee?)
fun main() {
val ceo = Employee("Da Boss",null)
val developer = Employee("Kevin",ceo)
println(managerName(developer))
println(managerName(ceo))
}
fun managerName(employee: Employee) : String? = employee.manager?.name
运行结果:
Da Boss
null
2. Elvis 运算符 “?:”
Kotlin 有方便的运算符来提供代替 null 的默认值,它被称作 Elvis 运算符,我们在 2.3 的基础上增加红框内的代码,使得 name 为空的时候将返回值设为 UnKnow:
class Employee(val name: String, val manager:Employee?)
fun main() {
val ceo = Employee("Da Boss",null)
val developer = Employee("Kevin",ceo)
println(managerName(developer))
println(managerName(ceo))
}
fun managerName(employee: Employee) : String? =
employee.manager?.name ?:"UnKnow"
运行结果:
Da Boss
UnKnow
3. 安全转换 ":as ?"
安全转换运算符会尝试把值转换成指定的类型,如果类型不合适就返回 null
data class Person(val name: String,val age: Int)
fun main() {
val person = Person("Kevin",18)
val person2 = Person("Kevin",25)
println(person2.comparePerson(person))
}
fun Person.comparePerson(other : Any ?) : Boolean {
val otherPerson = other as? Person ?: return false
return name == otherPerson.name
}
输出结果:
true
4. 非空断言 "!!"
非空断言 是 Kotlin 提供给你的最简单直率的处理可空类型的工具,它使用 !! 表示,可以把任何值转换成非空类型。
class HomeFragment : Fragment(R.layout.fragment_home) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rv_fruit.layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false)
rv_fruit.adapter = MyAdapter()
}
inner class MyAdapter : RecyclerView.Adapter<MyViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = LayoutInflater.from(context)
.inflate(R.layout.item_fruit,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
// kotlin 三种方式加载图片资源
holder.itemView.iv_fruit.setImageResource(R.mipmap.ic_apple)
// context!! 表示context 不为null
holder.itemView.iv_fruit.setImageDrawable(
ContextCompat.getDrawable(
context!!,
R.mipmap.ic_apple
)
)
}
override fun getItemCount(): Int {
return 20
}
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {}
}
5. let 函数
当可空参数最常见的一种用法就是被传递给一个接收非空参数的函数之前,需要进行相应的检查。
fun main() {
val nullEmail: String ? = "nullEmail"
nullEmail?.let { send(nullEmail) }
}
fun send(email: String) {
println("sending email to $email")
}
let 函数只在 nullEmail 的值非空时才被调用,所以就能在 lambda 中把 nullEmail 当做非空的实参来使用。