Kotlin 是什么
Kotlin
是一門(mén)運(yùn)行在JVM
之上的語(yǔ)言。
它由Jetbrains
創(chuàng)建,而Jetbrains
則是諸多強(qiáng)大的工具(如知名的Java IDE IntelliJ IDEA
)背后的公司。Kotlin
是一門(mén)非常簡(jiǎn)單的語(yǔ)言,其主要目標(biāo)之一就是提供強(qiáng)大語(yǔ)言的同時(shí)又保持簡(jiǎn)單且精簡(jiǎn)的語(yǔ)法。
kotlin 特性
其主要特性如下所示:
- 輕量級(jí):這一點(diǎn)對(duì)于
Android
來(lái)說(shuō)非常重要。項(xiàng)目所需要的庫(kù)應(yīng)該盡可能的小。Android
對(duì)于方法數(shù)量有嚴(yán)格的限制,Kotlin
只額外增加了大約6000個(gè)方法。 - 互操作:
Kotlin
可與Java
語(yǔ)言無(wú)縫通信。這意味著我們可以在Kotlin
代碼中使用任何已有的Java
庫(kù);因此,即便這門(mén)語(yǔ)言還很年輕,但卻已經(jīng)可以使用成百上千的庫(kù)了。除此之外,Kotlin
代碼還可以為Java
代碼所用,這意味著我們可以使用這兩種語(yǔ)言來(lái)構(gòu)建軟件。你可以使用Kotlin
開(kāi)發(fā)新特性,同時(shí)使用Java
實(shí)現(xiàn)代碼基的其他部分。 - 強(qiáng)類型:我們很少需要在代碼中指定類型,因?yàn)榫幾g器可以在絕大多數(shù)情況下推斷出變量或是函數(shù)返回值的類型。這樣就能獲得兩個(gè)好處:簡(jiǎn)潔與安全。使用
var
聲明可變參數(shù),val
聲明不可變參數(shù)var
:var
是一個(gè)可變變量,這是一個(gè)可以通過(guò)重新分配來(lái)更改為另一個(gè)值的變量。這種聲明變量的方式和Java
中聲明變量的方式一樣。val
:val
是一個(gè)只讀變量,這種聲明變量的方式相當(dāng)于java
中的final
變量。一個(gè)val
創(chuàng)建的時(shí)候必須初始化,因?yàn)橐院蟛荒鼙桓淖儭?上段代碼: var name = "ztz" println(name) name = "yif" println(name) val finalValue = "i v"; println(finalValue); 結(jié)果如下: ztz yif iv - 空安全:
Java
最大的一個(gè)問(wèn)題就是null
。如果沒(méi)有對(duì)變量或是參數(shù)進(jìn)行null
判斷,那么程序當(dāng)中就有可能拋出大量的NullPointerException
,然而在編碼時(shí)這些又是難以檢測(cè)到的。Kotlin
使用了顯式的null
,這會(huì)強(qiáng)制我們?cè)诒匾獣r(shí)進(jìn)行null
檢查。 - 語(yǔ)法糖
- 類的簡(jiǎn)化,隱式getter()、setter()
- 接口的默認(rèn)實(shí)現(xiàn)
- lambda與高階函數(shù)
- 空指針安全,編譯時(shí)期的空指針檢查
- 流式集合操作 map(), forEach()
- 新特性
- 函數(shù)拓展、屬性拓展
- 屬性代理
Kotlin 輕量級(jí)開(kāi)發(fā)
Null安全
Kotlin
是null
安全的。如果一個(gè)類型可能為null
,那么我們就需要在類型后面加上一個(gè)?
。這樣,每次在使用該類型的變量時(shí),我們都需要進(jìn)行null
檢查。比如說(shuō),如下代碼將無(wú)法編譯通過(guò):
var artist: Artist? = null?
artist.print()
第2行會(huì)顯示一個(gè)錯(cuò)誤,因?yàn)闆](méi)有對(duì)變量進(jìn)行null
檢查。我們可以這樣做:
if (artist != null) {
? artist.print()?
}
這展示了Kotlin
另一個(gè)出色的特性:智能類型轉(zhuǎn)換。如果檢查了變量的類型,那就無(wú)需在檢查作用域中對(duì)其進(jìn)行類型轉(zhuǎn)換。這樣,我們現(xiàn)在就可以在if
中將artist
作為Artist
類型的變量了。這對(duì)于其他檢查也是適用的。還有一種更簡(jiǎn)單的方式來(lái)檢查null
,即在調(diào)用對(duì)象的函數(shù)前使用?
。甚至還可以通過(guò)Elvis
運(yùn)算符?
提供另外一種做法:
val name = artist?.name ?: ""
數(shù)據(jù)類data
在Java
中,如果想要?jiǎng)?chuàng)建數(shù)據(jù)類或是POJO
類(只保存了一些狀態(tài)的類),我們需要?jiǎng)?chuàng)建一個(gè)擁有大量字段、getters
與setters
的類,也許還要提供toString
與equals
方法:
public class Artist {
private long id;
private String name;
private String url;
private String mbid;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMbid() {
return mbid;
}
public void setMbid(String mbid) {
this.mbid = mbid;
}
@Override public String toString() {
return "Artist{" +
"id=" + id +
", name='" + name + '\'' +
", url='" + url + '\'' +
", mbid='" + mbid + '\'' +
'}';
}
}
在Kotlin
中,上述代碼可以寫(xiě)成下面這樣:
data class Artist (?
var id: Long,
var name: String,
var url: String,
var mbid: String)
Kotlin
使用屬性而非字段?;旧希瑢傩跃褪亲侄渭由掀?code>getter與setter
。
互操作
Kotlin
提供了一些非常棒的互操作特性,這對(duì)于Android
開(kāi)發(fā)幫助非常大。其中之一就是擁有單個(gè)方法的接口與lambda
表達(dá)式之間的映射。這樣,下面這個(gè)單擊監(jiān)聽(tīng)器:
view.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
toast("Click")?
}
?})
可以寫(xiě)成這樣:
view.setOnClickListener { toast("Click") }
此外,getters
與setters
都會(huì)自動(dòng)映射到屬性上。這并不會(huì)造成性能上的損失,因?yàn)樽止?jié)碼實(shí)際上只是調(diào)用原來(lái)的getters
與setters
。如下代碼所示:
supportActionBar.title = title
textView.text = title
contactsList.adapter = ContactsYifAdapter()
Lambda表達(dá)式
Lambda
表達(dá)式會(huì)在極大程度上精簡(jiǎn)代碼,不過(guò)重要的是借助于Lambda
表達(dá)式,我們可以做到之前無(wú)法實(shí)現(xiàn)或是實(shí)現(xiàn)起來(lái)非常麻煩的事情。借助于Lambda
表達(dá)式,我們可以以一種更加函數(shù)式的方式來(lái)思考問(wèn)題。Lambda
表達(dá)式其實(shí)就是一種指定類型,并且該類型定義了一個(gè)函數(shù)的方式。比如說(shuō),我們可以像下面這樣定義一個(gè)變量:
val listener: (View) -> Boolean
該變量可以聲明一個(gè)函數(shù),它接收一個(gè)view
并返回這個(gè)函數(shù)。我們需要通過(guò)閉包的方式來(lái)定義函數(shù)的行為:
val listener = { view: View -> view is TextView }
上面這個(gè)函數(shù)會(huì)接收一個(gè)View
,如果該view
是TextView
的實(shí)例,那么它就會(huì)返回true
。由于編譯器可以推斷出類型,因此我們無(wú)需指定。還可以更加明確一些:
val listener: (View) -> Boolean = { view -> view is TextView }
借助于Lambda
表達(dá)式,我們可以拋棄回調(diào)接口的使用。只需設(shè)置希望后面會(huì)被調(diào)用的函數(shù)即可:
fun asyncOperation(value: Int, callback: (Boolean) -> Unit) {
...
callback(true)?
}
asyncOperation(5) { result -> println("result: $result") }
還有一種更加簡(jiǎn)潔的方式,如果函數(shù)只接收一個(gè)參數(shù),那就可以使用保留字it
:
asyncOperation(5) { println("result: $it") }
高階函數(shù)
lambda`本身作為一等公民,它是有類型的。比如下面這個(gè)加法表達(dá)式sum的類型為`(Int, Int) -> Int。
val sum: (Int, Int) -> Int = { x, y -> x+y }
一個(gè)變量有類型是再自然不過(guò)的事。而高階函數(shù)的入?yún)⑴c返回值既然是lambda
,那其類型奇怪一點(diǎn)也很正常。
fun main(args: Array<String>) {
// 自定義高階函數(shù), lambda 表達(dá)式 作為入?yún)?/span>
listOf("1", "2", "3", "4").myForEach { println(it) }
// 自定義高階函數(shù), lambda 表達(dá)式 作為返回值
// getLogger()("I'm a Closure")
var logger = getLogger()
logger("I'm a Closure")
}
/**
* 接受一個(gè) lambda 表達(dá)式, 作為遍歷任務(wù)
*/
fun <T> List<T>.myForEach(doTask: (T) -> Unit){
for(item in this)
doTask(item)
}
/**
* 返回一個(gè) lambda 表達(dá)式(閉包), 如: 日志輸出工具 logger
*/
fun getLogger(): (String) -> Unit{
// return { println(it) }
return fun (it: String){
println(it)
}
}
PS: 看到getLogger()
這種用法,你大概意識(shí)到可以像js
那樣寫(xiě)閉包了。
接口的默認(rèn)實(shí)現(xiàn)
顧名思義,它便是指接口可以和抽象類一樣,有方法體的默認(rèn)實(shí)現(xiàn)。 我把它歸結(jié)在語(yǔ)法糖里,是因?yàn)?code>java8中早已有了一模一樣的東西,對(duì)應(yīng)的關(guān)鍵字叫default
。
interface A {
fun foo() { println("A") } // 默認(rèn)實(shí)現(xiàn), 打印"A"
fun bar()
}
interface B {
fun foo() { println("B") }
fun bar() { println("bar") }
}
// 多繼承時(shí),顯式指定 super<A>.foo() 以去沖突
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super.bar()
}
}
流式集合操作 map(), forEach()
流式集合操作符,算是很普遍了,任何語(yǔ)言里都有,然而不支持函數(shù)式的話,寫(xiě)起來(lái)比較臃腫。 如下例子,一些操作符的銜接,使得操作邏輯十分清晰,之后需求變動(dòng),比如降序改為升序,也只需改動(dòng)sortedDescending()
一行,十分靈活。
fun main(args: Array<String>){
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
list.filter { it%2==0 } // 取偶數(shù)
.map{ it*it } // 平方
.sortedDescending() // 降序排序
.take(3) // 取前 3 個(gè)
.forEach { println(it) } // 遍歷, 打印
}
// 輸出:
100
64
36
拓展
拓展這個(gè)東西,貌似是以裝飾者模式來(lái)做的。它的效果是在不改源碼的基礎(chǔ)上,添加功能。比如我們要在Activity
上加一個(gè)toast()
,完全不用卸載基類里。這樣簡(jiǎn)化了很多工作,尤其是對(duì)一些已打成jar
包的類。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-733411.html
fun Activity.toast(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
/**
* @author yif
*
* 函數(shù)拓展, 屬性拓展
*/
fun main(args: Array<String>) {
val list = listOf("1", "2", "3", "4")
// 函數(shù)拓展
list.myForEach { println(it) }
// 屬性拓展
println("last: ${list.lastItem}")
}
/**
* 拓展 List 類, 加一個(gè)自定義的遍歷方法
*/
fun <T> List<T>.myForEach(doTask: (T) -> Unit){
for(item in this)
doTask(item)
}
/**
* 拓展 List 類, 加一個(gè)自定義的長(zhǎng)度屬性
*/
val <T> List<T>.lastItem: T
get() = get(size - 1)
// 輸出:
1
2
3
4
last: 4
屬性代理
它把屬性的get()
、set()
代理給了一個(gè)類,以便可以在get()
和set()
時(shí)做一些額外的操作。如:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-733411.html
- 懶加載
- 觀察者(屬性變化時(shí),自動(dòng)發(fā)出通知)
- 屬性非空判斷 以懶加載為例,
lazySum
可能需要復(fù)雜的運(yùn)算,我們把它代理給lazy
。 可以看到,只有第一次加載進(jìn)行了計(jì)算,之后都是直接取值,提高了效率。 val lazySum: Int by lazy { println(“begin compute lazySum …”) var sum = 0 for (i in 0…100) sum += i println(“l(fā)azySum computed!n”) sum // 返回計(jì)算結(jié)果 } fun main(args: Array<String>) { println(lazySum) println(lazySum) } // 輸出: begin compute lazySum … lazySum computed! 5050 5050 AnkoAnko
是Kotlin
團(tuán)隊(duì)開(kāi)發(fā)的一個(gè)庫(kù),旨在簡(jiǎn)化Android
開(kāi)發(fā)。其主要目標(biāo)在于提供一個(gè)DSL
,使用Kotlin
代碼來(lái)聲明視圖: verticalLayout { val name = editText() button(“Say Hello”) { onClick { toast(“Hello, ${name.text}!”) } } } 它還提供了其他一些很有用的特性。比如說(shuō),導(dǎo)航到其他Activity
和傳值到其它界面: startActivity(“id” to res.id, “name” to res.name) startActivity<ContentActivity>( Pair(Constants.CONTENT_TITLE_KEY, useWebsiteBean.name), Pair(Constants.CONTENT_URL_KEY, useWebsiteBean.link), Pair(Constants.CONTENT_ID_KEY, useWebsiteBean.id) ) 總結(jié) Kotlin真的在很多方面都簡(jiǎn)化了Android的開(kāi)發(fā)工作。它會(huì)提升你的生產(chǎn)力,并且可以通過(guò)非常不同且更加簡(jiǎn)單的方式來(lái)解決一些常見(jiàn)的問(wèn)題。讓我們一起使用Kotlin來(lái)快速敏捷開(kāi)發(fā)吧。
更多Kotlin 資料可以掃碼免費(fèi)領(lǐng)?。。?!
到了這里,關(guān)于Kotlin 輕量級(jí)Android開(kāi)發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!