Kotlin簡(jiǎn)介
- 來(lái)自于著名的IDE IntelliJ IDEA(Android Studio基于此開(kāi)發(fā)) 軟件開(kāi)發(fā)公司 JetBrains(位于東歐捷克)
- 起源來(lái)自JetBrains的圣彼得堡團(tuán)隊(duì),名稱(chēng)取自俄羅斯圣彼得堡附近的一個(gè)小島(Kotlin Island)
- 一種基于JVM的靜態(tài)類(lèi)型編程語(yǔ)言,2017年谷歌I/O大會(huì)確定Kotlin為Android的官方語(yǔ)言
Kotlin應(yīng)用不同領(lǐng)域
- Kotlin-Script腳本編寫(xiě)
- Kotlin-Android項(xiàng)目開(kāi)發(fā)
- Kotlin-JavaScript前端項(xiàng)目開(kāi)發(fā)
- Kotlin-SpringBoot服務(wù)端項(xiàng)目開(kāi)發(fā)
- Kotlin-Native項(xiàng)目開(kāi)發(fā)
Kotlin開(kāi)發(fā)環(huán)境
- 需要在IDE中安裝Kotlin插件;Android Studio3.0以上
Kotlin的優(yōu)點(diǎn)
- 簡(jiǎn)潔(不用判斷NullPointException,不需要寫(xiě)分號(hào)等)
- 100% 兼容 Java
- 類(lèi)型自動(dòng)轉(zhuǎn)換并使用
定義變量
val a: Int = 1 // 顯式標(biāo)明類(lèi)型,立即賦值
val b = 2 // 自動(dòng)推斷出 `Int` 類(lèi)型
var c: Int // 如果沒(méi)有初始值類(lèi)型不能省略
c = 3 // 明確賦值
var和val的區(qū)別
- var是一個(gè)可變變量,這種聲明變量的方式和java中聲明變量的方式一樣。
- val是一個(gè)只讀變量,這種聲明變量的方式相當(dāng)于java中的final變量,以后不能被改變。
var name = "我是可改變的"
println(name)
name = "我真的是可改變"
println(name)
val finalValue = "我是不可改變的";
println(finalValue);
類(lèi)定義
- 在Kotlin中所有類(lèi)都有一個(gè)共同的超類(lèi)
Any
//類(lèi)定義,繼承類(lèi)和實(shí)現(xiàn)接口
class FeedBackActivity : NativeBaseActivity(), View.OnLongClickListener, BitmapUtil.SaveImageCall {
}
- 創(chuàng)建類(lèi)的實(shí)例
val invoice = Invoice()
val customer = Customer("Joe Smith")
//注意 Kotlin 并沒(méi)有 new 關(guān)鍵字。
函數(shù)定義
Kotlin 中的函數(shù)使用 fun 關(guān)鍵字聲明,參數(shù)即 name: type。參數(shù)用逗號(hào)隔開(kāi)
fun double(x: Int): Int {
return 2 * x
}
- Int 返回類(lèi)型可以省略
fun sum(a: Int, b: Int): Int {
return a + b
}
也可以
fun sum(a: Int, b: Int) = a + b
- 減少方法重載
//支持默認(rèn)參數(shù)值,減少方法重載
fun showToast(message: String, duration:Int = Toast.LENGTH_LONG) {
Toast.makeText(this, message, duration).show()
}
//調(diào)用方式:沒(méi)有默認(rèn)值的參數(shù),調(diào)用時(shí),必須填寫(xiě)
showToast("toast");
showToast("toast", Toast.LENGTH_LONG);
- main方法比較
//Java
public static void main(String[] args){
}
//Kotlin
fun main(args:Array<String>){
}
主次構(gòu)造函數(shù)
在Kotlin中的一個(gè)類(lèi)可以有一個(gè)主構(gòu)造函數(shù)和一個(gè)或多個(gè)次構(gòu)造函數(shù)
- 主構(gòu)造函數(shù):帶有類(lèi)名的為主構(gòu)造函數(shù)(只有一個(gè))
- 主構(gòu)造函數(shù)不能包含任何的代碼。初始化的代碼可以放到以 init 關(guān)鍵字作為前綴的初始化塊
- 主構(gòu)造函數(shù)中聲明的屬性可以是可變的(var)或只讀的(val)
//如果構(gòu)造函數(shù)有注解或可見(jiàn)性修飾符,這個(gè) constructor 關(guān)鍵字是必需的,并且這些修飾符在constructor前面:
class Customer public @Inject constructor(name: String) { …… }
//無(wú)修飾可不寫(xiě)constructor關(guān)鍵字
class Customer (name: String) {
var a :Int = 1
init{……}
}
- 次構(gòu)造函數(shù):不帶類(lèi)名并且有constructor關(guān)鍵字修飾的函數(shù)為次構(gòu)造函數(shù)(可以一個(gè)或多個(gè)),并且只能存在主構(gòu)造函數(shù)代碼塊之內(nèi)
//如果類(lèi)有一個(gè)主構(gòu)造函數(shù),每個(gè)次構(gòu)造函數(shù)需要委托給主構(gòu)造函數(shù), 可以直接委托或者通過(guò)別的次構(gòu)造函數(shù)間接委托。委托到同一個(gè)類(lèi)的另一個(gè)構(gòu)造函數(shù)用 this 關(guān)鍵字即可:
class Person(val name: String) {
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
- 無(wú)參構(gòu)造函數(shù):
- 如果沒(méi)有構(gòu)造函數(shù),將會(huì)默認(rèn)一個(gè)無(wú)參數(shù)構(gòu)造函數(shù)
- 如果主構(gòu)造函數(shù)的所有的參數(shù)都有默認(rèn)值,編譯器會(huì)生成一個(gè)額外的無(wú)參構(gòu)造函數(shù),它將使用默認(rèn)值。
//如構(gòu)造函數(shù)為私有,需用private修飾
class DontCreateMe public constructor () {
}
class Customer(val customerName: String = ""){}
函數(shù)調(diào)用
val result = double(2)
Sample().foo() // 創(chuàng)建類(lèi) Sample 實(shí)例并調(diào)用 foo
字符串模板
- 字符串可以包含模板表達(dá)式,以$開(kāi)始
val book = Book("Thinking In Java", 59.0f, "Unknown")
val extraValue = "extra"
Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")
區(qū)間
區(qū)間表達(dá)式由具有操作符形式 .. 的 rangeTo 函數(shù)輔以 in 和 !in 形成。
if (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}
//順序
for (i in 1..4) print(i) // 輸出“1234”
for (i in 4..1) print(i) // 什么都不輸出
//倒序
for (i in 4 downTo 1) print(i) // 輸出“4321”
//要?jiǎng)?chuàng)建一個(gè)不包括其結(jié)束元素的區(qū)間,可以使用 until 函數(shù):
for (i in 1 until 10) { // i in [1, 10) 排除了 10
println(i)
}
//能否以不等于 1 的任意步長(zhǎng)迭代數(shù)字? 當(dāng)然沒(méi)問(wèn)題, step() 函數(shù)有助于此:每循環(huán)到第二個(gè)元素就剔除
for (i in 1..4 step 2) print(i) // 輸出“13”
for (i in 4 downTo 1 step 2) print(i) // 輸出“42”
控制流:if、when、for、while
if表達(dá)式
if和Java用法一致
val max = if (a > b) a else b
when表達(dá)式
when它能完全取代switch/case,也可以用來(lái)取代 if-else if鏈,并且還有很多新的特性。
如果其他分支都不滿(mǎn)足條件將會(huì)求值else分支。 如果 when 作為一個(gè)表達(dá)式使用,則必須有 else 分支, 除非編譯器能夠檢測(cè)出所有的可能情況都已經(jīng)覆蓋了。
//分支條件可以是:Int,區(qū)間,方法,字符串,對(duì)象等
when (x) {
0, 1 -> print("x == 0 or x == 1")
in 2 -> print("x == 2")
in 3..8 -> print("x == 3..8")
parseInt(s)-> print("parseInt")
is String -> print("x is String")
else -> print("otherwise")
}
fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix")//智能轉(zhuǎn)換
else -> false
}
//when 也可以用來(lái)取代 if-else if鏈。 如果不提供參數(shù),所有的分支條件都是簡(jiǎn)單的布爾表達(dá)式,而當(dāng)一個(gè)分支的條件為真時(shí)則執(zhí)行該分支:
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
for 循環(huán)
for (item in collection) print(item)
//循環(huán)體可以是一個(gè)代碼塊。
for (item: Int in ints) {
// ……
}
for (i in 1..3) {
println(i)//輸出“123”
}
for (i in 6 downTo 0 step 2) {
println(i)//輸出“6420”
}
//如果想索引遍歷,可以通過(guò)indices函數(shù)
for (i in array.indices) {
println(array[i])
}
//或者你可以用庫(kù)函數(shù) withIndex:
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
//輸出:
the element at 0 is a
the element at 1 is b
the element at 2 is c
While 循環(huán)
while 和 do..while 照常使用,省略
Kotlin 有三種結(jié)構(gòu)化跳轉(zhuǎn)表達(dá)式:
- return,默認(rèn)從最直接包圍它的函數(shù)或者匿名函數(shù)返回。
- break,終止最直接包圍它的循環(huán)。
- continue,繼續(xù)下一次最直接包圍它的循環(huán)。
特殊符號(hào)?和!!
?:表示當(dāng)前是否對(duì)象可以為空
!!: 表示當(dāng)前對(duì)象不為空的情況下執(zhí)行
private var cloth_Rv: RecyclerView ?= null
cloth_Rv!!.setHasFixedSize(true)
可見(jiàn)性修飾符
類(lèi)、對(duì)象、接口、構(gòu)造函數(shù)、方法、屬性和它們的 setter 都可以有 可見(jiàn)性修飾符。 在 Kotlin 中有這四個(gè)可見(jiàn)性修飾符:private、 protected、 internal 和 public。 如果沒(méi)有顯式指定修飾符的話(huà),默認(rèn)可見(jiàn)性是 public
- internal —— 能見(jiàn)到類(lèi)聲明的 本模塊內(nèi) 的任何客戶(hù)端都可見(jiàn)其 internal 成員
- 其它和Java一樣
重要關(guān)鍵字
Any
在Kotlin中所有類(lèi)都有一個(gè)共同的超類(lèi)Any,Any并不是Object
open
- 修飾類(lèi):表示能被繼承
- 修飾方法:表示需要重寫(xiě)
final、open、abstract、override對(duì)比
| 修飾符 | 相應(yīng)類(lèi)的成員 | 注解 |
|---|---|---|
| final | 不能被重寫(xiě) | 在kotlin中默認(rèn)所有的方法和類(lèi)都是final屬性 |
| open | 可以被重寫(xiě) | 需要被明確指出 |
| abstract | 必須要重寫(xiě) | 不能被實(shí)例化,默認(rèn)具有open屬性 |
| override | 覆寫(xiě)超類(lèi)的方法 | 如果沒(méi)有被指定為final,則默認(rèn)具有open屬性 |
companion 伴生對(duì)象
//可以省略Factory
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create()
內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)
- 內(nèi)部類(lèi)
//如果需要調(diào)用成員變量,需要用inner修飾內(nèi)部類(lèi)
class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}
val demo = Outer().Inner().foo() // == 1
- 匿名內(nèi)部類(lèi)
//匿名內(nèi)部類(lèi)
textView.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
//...
}
})
擴(kuò)展
函數(shù)擴(kuò)展可以讓你對(duì)任意類(lèi)進(jìn)行擴(kuò)展,而不用繼承等等復(fù)雜的操作。
對(duì)參數(shù)的解釋?zhuān)?/p>
- Context:表示函數(shù)的接收者,也就是函數(shù)擴(kuò)展的對(duì)象
- . :擴(kuò)展函數(shù)修飾符
- toast:擴(kuò)展函數(shù)的名稱(chēng)或者屬性名稱(chēng)
擴(kuò)展函數(shù)
fun Context.showToast(content: String, duration: Int = Toast.LENGTH_SHORT): Toast {
val toast = Toast.makeText(MyApplication.context, content, duration)
toast.show()
return toast
}
這樣只要是Context的子類(lèi),任何地方都可以調(diào)用Toast了
擴(kuò)展屬性
var View.padLeft: Int
set(value) {
setPadding(value, paddingTop, paddingRight, paddingBottom)
}
get() {
return paddingLeft
}
//調(diào)用 textView.padLeft = 16
Any擴(kuò)展函數(shù)
apply
- apply 是 Any 的擴(kuò)展函數(shù),因而所有類(lèi)型都能調(diào)用。
- apply 接受一個(gè)lambda表達(dá)式作為參數(shù),并在apply調(diào)用時(shí)立即執(zhí)行,apply返回原來(lái)的對(duì)象。
- apply 主要作用是將多個(gè)初始化代碼鏈?zhǔn)讲僮?,提高代碼可讀性。
val task = Runnable { println("Running") }
val thread = Thread(task)
thread.setDaemon(true)
thread.start()
以上代碼可以簡(jiǎn)化為:
val task = Runnable { println("Running") }
Thread(task).apply { setDaemon(true) }.start()
如有問(wèn)題歡迎留言,感謝支持和關(guān)注。