關鍵字lateinit
在 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)
}
...
}
關於null值
Kotlin 提供了嚴格的可爲 null 性規則,可在您的整個應用中維護類型安全。在 Kotlin 中,默認情況下,對對象的引用不能包含 null 值。要爲變量賦予 null 值,您必須通過將 ? 添加到基本類型的末尾來聲明可爲 null 變量類型。
例如:
val name: String? = null
Delegates.notNull()
Delegate.notNull()代理主要用於可以不在構造器初始化時候初始化而是可以延遲到之後再初始化這個var修飾的屬性。適用於基本數據類型和引用類型。
例如:我們在android的 application 這樣寫 Context對象。
class App:Application(){
companion object{
var instance:App by Delegates.notnull()
}
override fun onCreate(){
super.onCreate()
instance = this
}
}
Elvis 操作符
當我們有一個可空的引用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
}
關鍵字in
//作爲區間使用
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")
}