- 字符串字面值可以包含模板表達式 ,即一些小段代碼,會求值並把結果合併到字符串中。 模板表達式以美元符($)開頭,由一個簡單的名字構成:
val s = "abc"
println("$s.length is ${s.length}") // 輸出“abc.length is 3”
- 當某個變量的值可以爲 null 的時候,必須在聲明處的類型後添加 ? 來標識該引用可爲空。
如果 str 的內容不是數字返回 null:
fun parseInt(str: String): Int? {
// ……
}
- 次構造函數
//如果類有一個主構造函數,每個次構造函數需要委託給主構造函數,
//可以直接委託或者通過別的次構造函數間接委託。委託到同一個類的另一個構造函數用 this 關鍵字即可
class Person(val name: String) {
var children: MutableList<Person> = mutableListOf<Person>();
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
- is 運算符檢測一個表達式是否某類型的一個實例。 如果一個不可變的局部變量或屬性已經判斷出爲某類型,那麼檢測後的分支中可以直接當作該類型使用,無需顯式轉換.
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
// `obj` 在這一分支自動轉換爲 `String`
return obj.length
}
- for 循環
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
//output
item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit
- when 表達式
when 既可以被當做表達式使用也可以被當做語句使用。如果它被當做表達式, 符合條件的分支的值就是整個表達式的值,如果當做語句使用, 則忽略個別分支的值。(像 if 一樣,每一個分支可以是一個代碼塊,它的值是塊中最後的表達式的值。)
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
fun main() {
println(describe(1))
println(describe("Hello"))
println(describe(1000L))
println(describe(2))
println(describe("other"))
}
//output:
One
Greeting
Long
Not a string
Unknown
- 伴生對象
類內部的對象聲明可以用 companion 關鍵字標記:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
fun main(){
val instance = MyClass().create()
}
可以省略伴生對象的名稱,在這種情況下將使用名稱 Companion:
class MyClass {
companion object { }
}
val x = MyClass.Companion
請注意,即使伴生對象的成員看起來像其他語言的靜態成員,在運行時他們仍然是真實對象的實例成員,而且,例如還可以實現接口:
interface Factory<T>{
fun create(): T
}
class MyClass{
companion object :Factory<MyClass>{
override fun create(): MyClass = MyClass()
}
}
val f:Factory<MyClass> = MyClass
- let函數
使用let函數處理需要針對一個可null的對象統一做判空處理.
let擴展函數的實際上是一個作用域函數,當你需要去定義一個變量在一個特定的作用域範圍內,let函數的是一個不錯的選擇.
object.let{
it.todo()//在函數體內使用it替代object對象去訪問其公有的屬性和方法
...
}
//另一種用途 判斷object爲null的操作
object?.let{//表示object不爲null的條件下,纔會去執行let函數體
it.todo()
}
//具體的使用例子
fun setEmptyView(layoutResId: Int) {
weakRecyclerView.get()?.let {
val view = LayoutInflater.from(it.context).inflate(layoutResId, it, false)
setEmptyView(view)
}
}
- var 和 val 的唯一區別在於 var 既有 getter 又有 setter,val 只有 getter 沒有 setter
var a = 3
// var a: Int = 3
// 省略可推斷類型.
var b = 3
// Warning: Redundant setter.
get() = field
// Warning: Redundant setter.
set(value) {
field = value
}
// 編譯錯誤: Property must be initialized or be abstract.
// var c: Int
// 編譯錯誤: Property must be initialized.
// var d
// get() = 3
val e
get() = 3
var f
get() = 3
// Warning: Redundant setter.
set(value) {}
val 屬性沒有 setter,就像 private val a = 0 的屬性與 Java 中的 private final 字段完全相同。
幕後字段 field,用來在 getter 和 setter 中訪問當前屬性,相當於 Java 中的 private 字段。
一定條件下屬性可以不賦予初始化值,對應在 Java 中不會生成字段,只會生成 getter 和 setter
收錄於這個人的博客
- 關鍵字with
它是將某對象作爲函數的參數,在函數塊內可以通過 this 指代該對象。返回值爲函數塊的最後一行或指定return表達式。可以看出with函數是接收了兩個參數,分別爲T類型的對象receiver和一個lambda函數塊.
fun main(args: Array<String>) {
val user = User("帶哥", 32, "110911")
val result = with(user) {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
110
}
println("result: $result")
}
//java
public static final void main(@NotNull String[] args) {
User user = new User("帶哥", 32, "110911");
String var4 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + user.getPhoneNum();
System.out.println(var4);
int result = 110;
String var3 = "result: " + result;
System.out.println(var3);
}
- run函數
它彌補了let函數在函數體內必須使用it參數替代對象,在run函數中可以像with函數一樣可以省略,直接訪問實例的公有屬性和方法,另一方面它彌補了with函數傳入對象判空問題,在run函數中可以像let函數一樣做判空處理.
fun main(args: Array<String>) {
val user = User("帶哥", 32, "110911")
val result = user.run {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
110
}
println("result: $result")
}
- apply關鍵字
是一個擴展函數,把this作爲參數傳遞,它返回this(即它本身).可以從下面的例子看到.
class User(val name: String, val age: Int, val phoneNum: String)
fun main(args: Array<String>) {
val user = User("hub", 11, "123123123")
val result = user.apply {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
}
println("result: $result")
}
//output
//my name is hub, I am 11 years old, my phone number is 123123123
//result: User@48140564
//實際運用中
// 正常方法
fun createInstance(args: Bundle) : MyFragment {
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
// 改進方法
fun createInstance(args: Bundle)
= MyFragment().apply { arguments = args }
- also
T.let返回不同類型的值,而T.also返回T本身即this.
class User(val name: String, val age: Int, val phoneNum: String)
fun main(args: Array<String>) {
val user = User("max", 11, "123123123")
//注意打印加花括號,否則打印的是地址
//使用it還代替this
val result = user.also {
println("my name is ${it.name}, I am ${it.age} years old, my phone number is ${it.phoneNum}")
}
println("result: $result")
}
最後我們看看這些函數直接的區別.圖片來自這裏.