Kotlin 筆記(一) 基礎(chǔ)知識點--java對比

創(chuàng)建對象

Java Kotlin
A a = new A() var a = A()

類型聲明

Java Kotlin
String s var s : String
final String s val s : String
class A extends B class A : B
class A implements B class A : B

字符串模板

Java Kotlin
String.format("%s今年%d歲", name, age); "${name}今年${age}歲"

方法

Java Kotlin
String text(int para1,String para2) { ... } fun test(para1: Int, para2: String): String { ... }

Kotlin 特性 : 函數(shù)參數(shù)默認(rèn)值和可變參數(shù)

對Kotlin函數(shù)中的某個參數(shù)可以用“=”號指定其默認(rèn)值,調(diào)用函數(shù)方法時可不不傳這個參數(shù)冷离,但其他參數(shù)需要用“=”號指定。下文例子中沒有傳遞參數(shù)para2灼芭,其實際值為默認(rèn)值"para2"

fun test(para1: Int, para2: String = "para2", para3: String): String { ... }

test(22, para3 = "hello")

可變參數(shù)值的話,需要用關(guān)鍵字vararg來定義。這里需要注意的是,一個函數(shù)僅能有一個可變參數(shù)叶圃。該可變參數(shù)不一定得是最后一個參數(shù),但當(dāng)這種情況下時践图,調(diào)用該方法掺冠,需要給其他未指明具體值的參數(shù)傳值。

fun test(vararg para1: String, para2: String): String { ... }

test("para1", "para4", "para5", para2 = "hello")

構(gòu)造函數(shù)

Kotlin

類的構(gòu)造函數(shù)分為==primary constructor==和==secondary constructor==码党,前者只能有一個德崭,而后者可以有多個悍及。如果兩者都未指定,則默認(rèn)為無參數(shù)的primary constructor接癌。
primary constructor是屬于類頭的一部分心赶,用constructor關(guān)鍵字定義,無可見性字段定義時可省略缺猛。初始化代碼需要單獨寫在init代碼塊中缨叫,==primary constructor的參數(shù)只能在init代碼塊和變量初始化時使用。==
secondary constructor也是用constructor關(guān)鍵字定義荔燎,必須要直接或間接代理primary constructor耻姥。

class Student(name: String) { // primary constructor
    var mName: String = name
    init {
        println("Student is called " + name)
    }

    constructor(age: Int, name: String):this(name) {
        println("Student is ${age} years old")
    }
}

繼承

Java Kotlin
Java中類默認(rèn)可被繼承,只有被final關(guān)鍵字修飾的類才不能被繼承 僅有被open修飾的類才可以被繼承

單例

Java Kotlin
用代碼實現(xiàn)單例 用關(guān)鍵詞 object 定義單例類
object Shop { // 不能有 primary constructor的參數(shù)  ,
    fun buySomething() {
        println("Bought it")
    }
}

Shop.buysomething() // 調(diào)用

靜態(tài)標(biāo)識與調(diào)用

Java Kotlin
static標(biāo)識一個類里的靜態(tài)屬性或方法 用companion修飾單例類object有咨,來實現(xiàn)靜態(tài)屬性或方法功能
class Mall(name: String) {

    // companion 伴隨對象 在一個類中 [唯一] 
    companion object Shop { // 與 java 不同,Kotlin 所有靜態(tài)方法和字段都寫在內(nèi)部單例類中
        val SHOP_NAME: String = "McDonald" // 等同于Java中寫public static String
        fun buySomething() { // 等同于Java中寫public static void
            println("Bought it")
        }
    }
    
}


Mall.buySomething() // 可直接調(diào)用,

if-else語句

Kotlin

Kotlin中的if-else語句與Java一致琐簇,結(jié)構(gòu)上都是if (條件A) { 條件A為真要執(zhí)行的操作 } else { 條件A為假要執(zhí)行的操作 }
這里主要要介紹的是Kotlin的一個特點,即if-else語句可以作為一個邏輯表達(dá)式使用座享。不僅如此婉商,邏輯表達(dá)式還可以以代碼塊的形式出現(xiàn),代碼塊最后的表達(dá)式作為該塊的值渣叛。

// 邏輯表達(dá)式的使用
fun maxNum(x: Int, y: Int): Int {
    var max = if (x > y) x else y
    return max
}
// 代碼塊形式的邏輯表達(dá)式
fun maxNumPlus(x: Int, y: Int): Int {
    var max = if (x > y) {
        println("Max number is x")
        x
    } else {
        println("Max number is y")
        y
    }
    return max
}

when語句

Java Kotlin
switch-case語句 有多種形式的條件表達(dá)丈秩。與if-else一樣Kotlin中的when也可以作為邏輯表達(dá)式使用
// 邏輯表達(dá)式的使用
fun judge(obj: Any) { // Any 相當(dāng)于 java中 Object 
    when (obj) {
        1 -> println("是數(shù)字1")
        -1, 0 -> println("是數(shù)字0或-1")
        in 1..10 -> println("是不大于10的正整數(shù)")
        "abc" -> println("是字符串a(chǎn)bc")
        is Double -> println("類型是雙精度浮點數(shù)")
        else -> println("其他操作")
    }
}

標(biāo)簽

Kotlin中可以對任意表達(dá)式進(jìn)行標(biāo)簽標(biāo)記,形式為abc@淳衙,xyz@蘑秽。而這些標(biāo)簽,可以搭配return箫攀、break肠牲、continue等跳轉(zhuǎn)行為來使用。

fun labelTest() {
    la@ for (i in 1..10) {
        println("outer index " + i)
        for (j in 1..10) {
            println("inner index " + j )
            if ( inner % 2 == 0) {
                break@la
            }
        }
    }
}

符號“?”

Kotlin中靴跛,當(dāng)我們定義一個變量時缀雳,其默認(rèn)就是非空類型。如果你直接嘗試給他賦值為null汤求,編譯器會直接報錯俏险。Kotlin中將符號“?”定義為安全調(diào)用操作符。變量類型后面跟?號定義扬绪,表明這是一個可空類型竖独。同樣的,在調(diào)用子屬性和方法時挤牛,也可以用字符?進(jìn)行安全調(diào)用莹痢。Kotlin的編譯器會在寫代碼時就檢查非空情況,因此下文例子中,當(dāng)s2有前置條件判斷為非空后竞膳,即便其本身是可空類型航瞭,也可以安全調(diào)用子屬性或方法。對于ifelse結(jié)構(gòu)的邏輯坦辟,Kotlin還提供了“?:”操作符刊侯,極大了簡化了代碼量又不失可讀性。Kotlin還提供“!!”雙感嘆號操作符來強制調(diào)用對象的屬性和方法锉走,無視其是否非空滨彻。這是一個挺危險的操作符,除非有特殊需求挪蹭,否則為了遠(yuǎn)離NPE亭饵,還是少用為妙。

var s1: String = "abc"
s1 = null // 這里編譯器會報錯
var s2: String? = "abc"
s2 = null // 編譯器不會報錯

var l1 = s1.length // 可正常編譯
var l2 = s2.length // 沒有做非空判斷梁厉,編譯器檢查報錯

if (s2 != null) s2.length // Java式的判空方案
s2?.length // Kotlin的安全調(diào)用操作符?辜羊。當(dāng)s2為null時,s2?.length也為null
if (s2 != null) s2.length else -1 // Java式判空的ifelse邏輯
s2?.length ?: -1 // Kotlin的elvis操作符
s2!!.length // 可能會導(dǎo)致NPE

擴展方法

擴展函數(shù)定義形式

在方法體內(nèi)是可以調(diào)用receiverType的對象中原本的方法

fun receiverType.functionName(params){
    body // 注: 在方法體中使用 this ,那么 this 代表receiverType的對象(調(diào)用者)
}
  • receiverType:表示函數(shù)的接收者词顾,也就是函數(shù)擴展的對象
  • functionName:擴展函數(shù)的名稱
  • params:擴展函數(shù)的參數(shù)八秃,可以為NULL

常見例子,其中 this 代表 context ,

fun Context.showLongToast(msg: String) {
    Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
}

擴展方法位置

簡單說可以分為兩種: class 里面 ,class 外面

  1. 在一個類里面寫擴展方法,這時,在其他類直接調(diào)用是不生效的.
class B {

    fun Student.doF(){
        doFly() // Student 中原本就存在的方法
    }

    fun dow2(s:Student){
        s.doF()
    }

}


// 調(diào)用
B().dow2(Student())

在其他類調(diào)用 student.doF() 是不生效的 ,只有創(chuàng)建B對象調(diào)用dow2(s),擴展方法才能被調(diào)用

  1. 單獨新建一文件,或者寫在類的外面,可全部任意調(diào)用,如上面toast的例子,將擴展方法寫在單獨的文件中,在任意activity或者擁有Context的類中都能調(diào)用
/**
* 單獨一個類
*/
package ****

import android.content.Context
import android.widget.Toast
import java.util.*

// 擴展方法
fun Context.showLongToast(msg: String) {
    Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
}


/**
* 一個類內(nèi) ,class 外
*/
fun Context.showLongToast(msg: String) {
    Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
}
class Student(name: String) {
    ...
}


// 調(diào)用
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        showLongToast("111")
    }
}

伴隨對象的擴展

伴隨對象通過“類名.”形式調(diào)用伴隨對象。假如對伴隨對象聲明了擴展函數(shù)該怎么調(diào)用呢计技?其調(diào)用方式與伴隨對象一樣喜德,都是通過用類名限定符來調(diào)用。當(dāng)然垮媒,擴展屬性也是這樣的。(伴隨對象companion 的使用,請看上文)

fun Student.Shop.doW(){
    println("伴隨對象的擴展函數(shù)")
}


//調(diào)用
Student.doW()

擴展函數(shù)名與原類中的函數(shù)名相同

相同時,調(diào)用時根據(jù)擴展函數(shù)寫的位置不同,會存在兩種情況

  1. 類外.setText()與 TextView 中的方法同名,但是在調(diào)用時,會全部提示出來
fun TextView.setText(msg: String) {
    this.setText("擴展函數(shù)"+msg)
}

但是就傲嬌的不按提示調(diào)用,生寫一個一樣的方法時,這種情況下航棱,總是會優(yōu)先使用成員函數(shù),而不是擴展

open class Person {
    fun doFly() {
        println("親生的")
    }
}

fun Person.doFly() {
    println("后生的")
}

fun main(args: Array<String>) {

    val person: Person = Person()
    person.doFly()
}

// Log打印
親生的
  1. 類內(nèi),通過下面的例子可以得出結(jié)論,當(dāng)出現(xiàn)重名 doFly() 時,會默認(rèn)調(diào)用this(也就是 Person)中的方法
open class Person {

    fun doFly() {
        println("Person do fly")
    }
}

class MyInfo {

    fun doRun() {
        println("MyInfo do run")
    }

    fun doFly() {
        println("MyInfo do fly")
    }

    fun Person.doSwim() {
        doFly() // 默認(rèn)調(diào)用this(也就是 Person)中的方法
        doRun()
    }

    fun doSomething(person: Person) {
        person.doSwim()
    }
}

// 測試實例
fun main(args: Array<String>) {

    val myInfo: MyInfo = MyInfo()
    val person: Person = Person()
    myInfo.doSomething(person)
}
// Log  
Person do fly
MyInfo do run

但是如果也需要調(diào)用 MyInfo 中的doFly(),那么在
doFly()前面加上 "this@MyInfo. " 即可.

  fun Person.doSwim() {
        doFly()
        this@MyInfo.doFly()
        doRun()
}

// Log
Person do fly
MyInfo do fly
MyInfo do run

接收者可為NULL

調(diào)用者對象為空時,也可以調(diào)用

fun Person.doFly() {

    if (null == this) {
        println("null")
    }
    println("doFly")
}

擴展屬性

擴展屬性, 即 Extension Property , 即把某些函數(shù)添加為數(shù)據(jù), 使用”=”, 直接設(shè)置或使用睡雇。


val List.lastIndex: Int 
get() = size - 1

注:
由于擴展屬性實際上不會向類添加新的成員, 因此無法讓一個擴展屬性擁有一個后端域變量. 所以,對于擴展屬性不允許存在初始化器. 擴展屬性的行為只能通過明確給定的取值方法與設(shè)值方法來定義,也就意味著擴展屬性只能被聲明為val而不能被聲明為var.如果強制聲明為var饮醇,即使進(jìn)行了初始化它抱,在運行也會報異常錯誤,提示該屬性沒有后端域變量朴艰。

數(shù)據(jù)類

Java中數(shù)據(jù)model观蓄,通常都是由多個屬性和對應(yīng)的getter、setter組成祠墅。當(dāng)有大量多屬性的數(shù)據(jù)類時侮穿,不僅這些類會因為大量的getter和setter方法而行數(shù)爆炸,也使整個工程方法數(shù)驟增毁嗦。Kotlin中也做了這層特性優(yōu)化亲茅,提供了數(shù)據(jù)類的簡單實現(xiàn)。不用再寫get和set方法,這些都由編譯器背后去做克锣,你得到的是一個清爽干凈的數(shù)據(jù)類茵肃。具體使用參考下面的例子。

data class Student (
    var name: String,
    var age: Int,
    var hobby: String?,
    var university: String = "NJU"
)
fun printInfo() {
    var s: Student = Student("Ricky", 25, "playing Gwent")
    println("${s.name} is from ${s.university}, ${s.age} years old, and likes ${s.hobby}")
}

為了保證生成代碼的一致性和有意義的方法袭祟,數(shù)據(jù)類對象必須滿足一下要求

  • 構(gòu)造函數(shù)必須至少有一個參數(shù)
  • 所有的構(gòu)造函數(shù)參數(shù)必須標(biāo)注val或者var验残;
  • 數(shù)據(jù)類對象不能是 abstract, open, sealed or inner;
  • 數(shù)據(jù)類對象不能繼承其他類,但是可以實現(xiàn)接口
  • 在Java虛擬機里巾乳,如果生成的類需要有一個無參數(shù)的構(gòu)造函數(shù)您没,所有屬性的默認(rèn)值必須有一個具體的值,

componentN()

類對象里想鹰,有幾個屬性紊婉,會有幾個這個方法componentN(),比如上面的示例辑舷,調(diào)用方法 s.name 和 s.component1() 效果是一樣的

復(fù)制

我們經(jīng)常有這么一個使用場景:我么需要復(fù)制一個類對象喻犁,但是改變它的某些屬性,保持剩余其他的屬性值不變何缓。這就需要用到copy()函數(shù)實現(xiàn)肢础。對于上面的User類,可以如下實現(xiàn)復(fù)制:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

// 調(diào)用
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

相關(guān)文檔

Kotlin-擴展;
Kotlin 基礎(chǔ)學(xué)習(xí)+快速實踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碌廓,一起剝皮案震驚了整個濱河市传轰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谷婆,老刑警劉巖慨蛙,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纪挎,居然都是意外死亡期贫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門异袄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來通砍,“玉大人,你說我怎么就攤上這事烤蜕》馑铮” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵讽营,是天一觀的道長虎忌。 經(jīng)常有香客問我,道長斑匪,這世上最難降的妖魔是什么呐籽? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任锋勺,我火速辦了婚禮,結(jié)果婚禮上狡蝶,老公的妹妹穿的比我還像新娘庶橱。我一直安慰自己,他們只是感情好贪惹,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布苏章。 她就那樣靜靜地躺著,像睡著了一般奏瞬。 火紅的嫁衣襯著肌膚如雪枫绅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天硼端,我揣著相機與錄音并淋,去河邊找鬼。 笑死珍昨,一個胖子當(dāng)著我的面吹牛县耽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镣典,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼兔毙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了兄春?” 一聲冷哼從身側(cè)響起澎剥,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赶舆,沒想到半個月后哑姚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡芜茵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年蜻懦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夕晓。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖悠咱,靈堂內(nèi)的尸體忽然破棺而出蒸辆,到底是詐尸還是另有隱情,我是刑警寧澤析既,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布躬贡,位于F島的核電站,受9級特大地震影響眼坏,放射性物質(zhì)發(fā)生泄漏拂玻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檐蚜。 院中可真熱鬧魄懂,春花似錦、人聲如沸闯第。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咳短。三九已至填帽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咙好,已是汗流浹背篡腌。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勾效,地道東北人嘹悼。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像葵第,于是被迫代替她去往敵國和親绘迁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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