Kotlin

什么是Kotlin歉秫?

Kotlin是由JetBrains設(shè)計(jì)并開源的JVM編程語(yǔ)言蛾洛。Kotlin是使用Java開發(fā)者的思維創(chuàng)建的,Intellij作為它主要的開發(fā)IDE雁芙,因此對(duì)于Android開發(fā)者來(lái)說(shuō)它非常易于學(xué)習(xí)并能與AS和Gradle完美結(jié)合轧膘。
它的主要特點(diǎn)有:
1、簡(jiǎn)潔(函數(shù)式編程減少很多代碼)
2兔甘、安全(編譯時(shí)就處理了各種空指針的情況)
3谎碍、輕量級(jí)(Kotlin核心庫(kù)僅有不到7000個(gè)方法,大致和support-v4一樣)
4洞焙、高交互性(與Java混合編程)
5蟆淀、提供了更多特性

使用配置

1、Android Studio 安裝插件 Kotlin(原本還有 Kotlin Extensions For Android澡匪,已合入Kotlin)
2熔任、build.gradle 配置

buildscript {
    ext.kotlin_version = '1.0.5-2'
    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
    }
}

apply plugin: 'kotlin-android‘
apply plugin: 'kotlin-android-extensions‘

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
}

基本語(yǔ)法

這里只列出一些與Java不同的地方,完整的語(yǔ)法參考文檔見文章最后鏈接
1仙蛉、基本類型
數(shù)值:Double笋敞,F(xiàn)loat,Long荠瘪,Int夯巷,Short赛惩,Byte
字符:Char
布爾:true,false

// 短類型不是長(zhǎng)類型的子類型趁餐,需要顯示轉(zhuǎn)換喷兼,數(shù)值和字符都有toXXX()方法
var a: Int = 100
var b: Long = a.toLong() 

數(shù)組:Array

// 可以通過(guò) asc[0] 或 asc.get(0) 訪問(wèn)元素
// 可以通過(guò) asc.forEach{} 或 for(str in asc) {} 遍歷元素
var emptyArray = emptyArray<String>() // []
var nullArray = kotlin.arrayOfNulls<String>(3) // [null, null, null]
var numArray = arrayOf(1, 2, 3) // [1, 2, 3]
var asc = Array(5, { i -> (i * i).toString() }) // ["0", "1", "4", "9", "16"]

字符串:String

var str = "hello world"
訪問(wèn)和遍歷元素同Array

字符串模板:

var name = "Bob"
println("My name is $name") // 打印 My name is Bob

var a = 10
var b = 20
println("The sum is ${a+b}") // 打印 The sum is 30

2、變量與常量

var x: Int = 5 // 定義變量
var y = 5 // 能推導(dǎo)出類型后雷,可省略類型聲明
y++

val x: Int = 5 // 定義常量
val y = 5  // 能推導(dǎo)出類型季惯,可省略類型聲明
val z: Int  // 當(dāng)沒有初始化值時(shí)必須聲明類型 
z=1  // 只能賦值一次

const val INT_ONE: Int = 1 // 編譯時(shí)可確定值的常量可以用const修飾,但只能放在文件最外層

3臀突、流程控制
if表達(dá)式:

var max = if (a > b) a else b 

var max = if (a > b) {
    println("choose $a")
    a
} else {
    println("choose $b")
    b
}

for表達(dá)式和Range:

for (i in 0..4) println(i) // 0,1,2,3,4
for (i in 4 downTo 0) println(i) // 4,3,2,1,0
for (i in 0..4 step 2) println(i) // 0,2,4
for (i in 4 downTo 0 step 2) println(i) // 4,2,0
for (i in 0 until 4) println(i) // 0,1,2,3

When表達(dá)式:

when(x) { 
    0 -> print("x == 0")
    1,2 -> print("x == 1 or x == 2")
    in 1..10 -> print("x is in the range") 
    is Int -> print(x + 1)
    is String -> print(x.size() + 1) // 智能轉(zhuǎn)換
    else -> print("otherwise")
}

4勉抓、定義函數(shù)
fun + 函數(shù)名 + 參數(shù) + 返回值 + 函數(shù)體

fun sum(a: Int , b: Int): Int { return a + b } 
fun sum(a: Int, b: Int) = a + b  // 與上句等價(jià)
fun printSum(a: Int, b: Int): Unit { print( a + b) } // 沒有返回值時(shí)為Unit
fun printSum(a: Int, b: Int) { print( a + b) }  // Unit可省略

5、默認(rèn)參數(shù)
Java:

void introduce(String name, int age) {
    println("Hi, My name is " + name + ", I am " + age);
}
void introduce(String name) {
    introduce(name, 18);
}

Kotlin:

fun introduce(name: String, age: Int = 18) {
    println("Hi, My name is $name, I am $age")
}

調(diào)用:

introduce("Bob")
introduce("Bob", 20)

6候学、類與構(gòu)造函數(shù)
class + 類名 + 類頭 + 類主體

// 最簡(jiǎn)單的類定義
class Person

// 有一個(gè)主構(gòu)造函數(shù)的類藕筋,其中constructor關(guān)鍵字省略掉了
class Person(var id: Long, var name: String, var age: Int)

// constructor有private關(guān)鍵字修飾,不能省略
// 主構(gòu)造函數(shù)的初始化只能在類主體的init塊中
// 二級(jí)構(gòu)造函數(shù)在類主體中定義梳码,需要用this調(diào)用主構(gòu)造函數(shù)
class Person private constructor(var id: Long, var name: String, var age: Int) {
    init {
        print("Person initialized with id ${id} name ${name} age ${age}") 
    }
    constructor(person: Person) : this(person.id, person.name, person.age) {
    }
}

所有的類都有共同的父類 Any
沒有new關(guān)鍵字隐圾,直接像使用普通函數(shù)那樣使用構(gòu)造函數(shù)創(chuàng)建類實(shí)例:

var person = Person(1, "Bob", 20)

7、數(shù)據(jù)類
data class User(var id: Long, var name: String, var age: Int)
自動(dòng)實(shí)現(xiàn)了get掰茶、set方法以及toString暇藏、equals、hashCode濒蒋、copy等方法盐碱,支持映射對(duì)象到變量。

data class Forecast(var date: Date, var temp: Float, var details: String)

var f1 = Forecast(Date(), 27.5f, "Shiny day")
var f2 = f1.copy(temp = 30f) // 變量名不可隨意
var (date, temp, details) = f1 // 變量名可以隨意沪伙,按順序映射

8甸各、繼承
Kotlin中所有的類和屬性以及方法都默認(rèn)是final的,如果需要被繼承則要加上open關(guān)鍵字焰坪,override標(biāo)記的方法默認(rèn)是open的趣倾,如果不想再被繼承可以加上final

open class Base {
    open fun f1(){}
    fun f2() {}
}
class Derived : Base() {
    override fun f1() {}
} 

9、接口
Kotlin中的接口可以有屬性和方法的默認(rèn)實(shí)現(xiàn)某饰,與抽象類的區(qū)別是接口的屬性是無(wú)狀態(tài)的儒恋,需要子類去重寫
Java:

public interface Flying {
    void fly();
}
public class Bird implements Flying {
    Wings wings = new BirdWings();
    @Override
    public void fly() {
        wings.move();
    }
}
public class Bat implements Flying {
    Wings wings = new BatWings();
    @Override
    public void fly() {
        wings.move();
    }
}

Kotlin:

interface Flying {
    var wings: Wings
    fun fly() = wings.move()
}
class Bird : Flying {
    override var wings: Wings = BirdWings()
}
class Bat : Flying {
    override var wings: Wings = BatWings()
} 

Kotlin中實(shí)現(xiàn)接口和繼承類一樣,都是通過(guò)冒號(hào) : 繼承黔漂,多個(gè)接口及類之間以逗號(hào) , 隔開诫尽,如果方法有多個(gè)實(shí)現(xiàn)則必須在子類中重寫方法,可以通過(guò)super<Base>指定調(diào)用哪個(gè)父類中的方法

open class A {
    open fun f () {}
}
interface B {
    fun f() {}
}
class C : A() , B{
    override fun f() {
        super<A>.f() // 調(diào)用 A.f()
        super<B>.f() // 調(diào)用 B.f() 
    }
} 

10炬守、空安全

var user: User = null  // 這里不能通過(guò)編譯. user不能是null

var user: User? = null  // user可以是 null
user.name  // 無(wú)法編譯, user可能是null牧嫉,需要進(jìn)行判斷
user?.name  // 只有在user != null時(shí)才會(huì)執(zhí)行

if (user != null) {
    user.name  // 智能轉(zhuǎn)換. 如果我們?cè)谥斑M(jìn)行了空檢查,則不需要使用安全調(diào)用操作符調(diào)用 
} 

user!!.name  // 只有在確保user不是null的情況下才能這么調(diào)用,否則會(huì)拋出異常 

var name = user?.name ?: "empty"  // 使用Elvis操作符來(lái)給定一個(gè)在是null的情況下的替代值 

11酣藻、函數(shù)擴(kuò)展

fun String.toast(context: Context) {
    Toast.makeText(context, this, Toast.LENGTH_SHORT).show()
}
"abc".toast(context)

var sum = fun Int.(other: Int): Int = this + other 
1.sum(2)

12曹洽、Lambda表達(dá)式

(params) -> expression
(params) -> statement
(params) -> { statements }
如果參數(shù)沒用到可以省略為 () -> { statements } 甚至 { statements }

view.setOnClickListener{Log.d(TAG, "click view")}
listOf<Int>(1, 2, 3, 4, 5).filter { it > 2 }.map { it * it } // [9, 16, 25]

插件

kotlin-android-extensions插件主要提供了對(duì)Android的支持
例如:不再需要findViewById,可直接通過(guò)id引用xml中的View

textView.text = "Hello World!"; 
textView.setOnClickListener { toast(textView.text.toString()) }

anko插件引入了DSL(Domain Specific Language)的方式開發(fā)Android界面布局,主要目的是用代碼代替xml實(shí)現(xiàn)界面布局
使用前:

<RelativeLayout>
    <TextView
        android:id="@+id/sample_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="Sample text view"
        android:textSize="25sp" />
    <Button
        android:id="@+id/sample_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/sample_text_view"
        android:text="Sample button" />
</RelativeLayout>

使用后:

relativeLayout {
    val textView = textView("Sample text view") {
        textSize = 25f
    }.lparams {
        width = matchParent
        alignParentTop()
    }
    button("Sample button").lparams {
        width = matchParent
        below(textView)
    }
}

參考文檔

1辽剧、Kotlin API 中文文檔
https://github.com/huanglizhuo/kotlin-in-chinese

2送淆、Kotlin Android 開發(fā)中文文檔
https://github.com/wangjiegulu/kotlin-for-Android-developers-zh

3、Kotlin:Java 6 廢土中的一線希望
https://toutiao.io/posts/c55jha/preview

4怕轿、Kotlin 在線運(yùn)行
http://try.kotlinlang.org/

5偷崩、Android Studio中 code->Convert Java File to Kotlin File 自動(dòng)將Java文件轉(zhuǎn)換成Kotlin文件

另外由于Kotlin和Java之間的高交互性,可以一邊學(xué)習(xí)Kotlin的語(yǔ)法一邊一點(diǎn)點(diǎn)的替換現(xiàn)有代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撞羽,一起剝皮案震驚了整個(gè)濱河市阐斜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诀紊,老刑警劉巖智听,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渡紫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)考赛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門惕澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人颜骤,你說(shuō)我怎么就攤上這事唧喉。” “怎么了忍抽?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵八孝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鸠项,道長(zhǎng)干跛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任祟绊,我火速辦了婚禮楼入,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牧抽。我一直安慰自己嘉熊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布扬舒。 她就那樣靜靜地躺著阐肤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上孕惜,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天愧薛,我揣著相機(jī)與錄音,去河邊找鬼诊赊。 笑死厚满,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碧磅。 我是一名探鬼主播碘箍,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鲸郊!你這毒婦竟也來(lái)了丰榴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秆撮,失蹤者是張志新(化名)和其女友劉穎四濒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體职辨,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盗蟆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舒裤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喳资。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腾供,靈堂內(nèi)的尸體忽然破棺而出仆邓,到底是詐尸還是另有隱情,我是刑警寧澤伴鳖,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布节值,位于F島的核電站,受9級(jí)特大地震影響榜聂,放射性物質(zhì)發(fā)生泄漏搞疗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一须肆、第九天 我趴在偏房一處隱蔽的房頂上張望贴汪。 院中可真熱鬧,春花似錦休吠、人聲如沸扳埂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阳懂。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岩调,已是汗流浹背巷燥。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留号枕,地道東北人缰揪。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像葱淳,于是被迫代替她去往敵國(guó)和親钝腺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容