在 Kotlin 中,我们必须在声明对象时初始化对象的属性。
我们可以使用 lateinit 推迟属性初始化。使用 lateinit 时,应尽快初始化属性。
//调用 Fragment#onCreateView 之前,Fragment 中的 View 对象尚未准备好进行扩充,所以//我们需要使用这种方法来推迟 View 的属性初始化
class LoginFragment : Fragment() {
private lateinit var usernameEditText: EditText
private lateinit var passwordEditText: EditText
private lateinit var loginButton: Button
private lateinit var statusTextView: TextView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
usernameEditText = view.findViewById(R.id.username_edit_text)
passwordEditText = view.findViewById(R.id.password_edit_text)
loginButton = view.findViewById(R.id.login_button)
statusTextView = view.findViewById(R.id.status_text_view)
}
...
}
Kotlin 提供了严格的可为 null 性规则,可在您的整个应用中维护类型安全。在 Kotlin 中,默认情况下,对对象的引用不能包含 null 值。要为变量赋予 null 值,您必须通过将 ? 添加到基本类型的末尾来声明可为 null 变量类型。
例如:
val name: String? = null
Delegate.notNull()代理主要用于可以不在构造器初始化时候初始化而是可以延迟到之后再初始化这个var修饰的属性。适用于基本数据类型和引用类型。
例如:我们在android的 application 这样写 Context对象。
class App:Application(){
companion object{
var instance:App by Delegates.notnull()
}
override fun onCreate(){
super.onCreate()
instance = this
}
}
当我们有一个可空的引用b时候,我们可以说"如果b为空,我使用它,否则使用某个非空的值":
传统写法:
val l:Int = if(b != null)b.length else -1
Elvis写法
val l = b?.length ?: -1
如果 ?: 左侧表达式非空,elvis操作符就返回其左侧表达式,否则返回右侧表达式。请注意,当前仅当左侧为空时,才会对右侧表达式求值。
请注意:因为throw和return在kotlin中都是表达式,所以它们也可以用在Elvis操作符右侧,非常方便。
fun foo(node:Node):String?{
val parent = node.getParent ?:return null
val name = node.getName ?: throw IllegalArgumentException("name expected")
// .........
}
非空断言运算符(!!)将任何值转换为非空类型,若该值为空则抛出异常。我们可以写b!!,这会返回一个非空的b值(例如:我们例子中的String)或者如果b为空,就会抛出NPE异常。
val l = b!!.length
如果对象不是目标类型,那么常规类型转换可能会导致ClassCastException,另一个选择是使用安全的类型转换,如果尝试转换不成功则返回null。
val aInt:Int? = a as? Int
如果你有一个可空类型的元素集合,并且想要过滤非空元素,你可以使用filterNotNull
val nullableLst:List<Int?> = listOf(1,2,null,4)
val intList:List<Int> = nullableList.filterNotNull()
1.创建类的对象时,不管使用哪个构造器,都需要主构造器的参与。
2.在类的初始化过程中,首先执行的就是主构造器。
class User constructor(var name: String) {
// 直接调用主构造器
constructor(name: String, id: Int) : this(name) {
}
// 通过上一个次构造器,间接调用主构造器
constructor(name: String, id: Int, age: Int) : this(name, id) {
}
}
class User(var name: String) {
}
// 等价于:
class User(name: String) {
var name: String = name
}
//作为区间使用
when (number) {
in 1..10 -> println("x 在区间1..10之间")
in listOf(1, 2) -> println("x 在集合中")
!in 10..20 -> println("x 不在集合中")
else -> print("不在任何区间里")
}
//遍历使用,in 后面的变量可以是任何实现 Iterable 接口的对象
val array = intArrayOf(1, 2, 3, 4)
for (item in array) {
println("数组item $item")
}