kotlin項目基礎筆記

入職公司第三周時,項目組讓我用kotlin去完成一個內部使用的app。下面記錄一下kotlin相關筆記。因為app比較簡單,可能很多kotlin特性沒有用出來。學習kotlin過程中查找的資料放在了最后。
簡書不支持生成目錄,支持目錄結構的文檔地址

第一個kotlin的android項目實踐

開發環境

AS version: android stdio 3.0 bate 5
android stdio 3.0以上是支持直接創建kotlin項目的,如果是android stdio 3.0以下,需要額外的添加一些依賴。

kotlin幾個直觀的特性

如果看不懂下面的內容沒關系,后面會詳細的講,我也是菜鳥,看不懂就比較慌!

  1. java中必須使用;結尾。 而kotlin中一行代碼結束是不需要使用;結尾的。
  1. 一個文件下,不一定需要一個類名,只要新建一個kotlin類型的文件(文件擴展名 為.kt的文件),就可以直接寫代碼。
    eg: 定義一個名為BaseExtension.kt的文件,功能是對類擴展了一些方法。
package manage.ad.yiba.com.admanage.common.extension

import android.content.Context
import android.support.v7.app.AlertDialog
import android.util.Log
import android.widget.Toast
import manage.ad.yiba.com.admanage.common.BaseActivity


/**
 * Created by yh on 8/24/17.
 *  該kt文件用來對類的擴展
 */

//Context 基礎類的擴展
fun Context.toast(content: CharSequence, time: Int = Toast.LENGTH_LONG){
    Toast.makeText(this,content,time).show()
}

//擴展一個log方法
fun Any.log(tag: Any = "Tag",content: String?){

    Log.i(tag.toString(),content)
}
fun Any?.toString(): String {
    if (this == null) return "null"
// 在空檢查之后,`this` 被自動轉為非空類型,因此 toString() 可以被解
//    析到任何類的成員函數中
//    ChinaPerson("",2,"","","")
//    ChinaPerson("",2,"","","","")
    return toString()
}

fun BaseActivity.showDialogMessage(title: String = "", body: String, rightCode: ()->Unit = {System.exit(0)},leftCode: ()->Unit = {}) {
    var exitDialog: AlertDialog? = null
    val builder = AlertDialog.Builder(this)
    builder.setTitle(title).setMessage(body).setPositiveButton("OK") { dialog, which ->
        rightCode.invoke()
    }.setNeutralButton("Cancel"){dialog, which ->
        leftCode.invoke()
        try {
            exitDialog?.dismiss()
        }catch (e: Exception){
        }
    }

    exitDialog = builder.create()
    exitDialog.show()
}
  1. 一個擴展名為.kt文件中,可以定義多個類,這里定義的類跟javaBean是一個功能,這是在kotlin中的寫法。
    eg: 名為Response.kt的文件中,包含多個類
package manage.ad.yiba.com.admanage.moudle.adDeploy

import manage.ad.yiba.com.admanage.retrofit.BaseResponse
import java.io.Serializable

/**
 * Created by yh on 9/19/17.
 */
data class AdDeployResponse(var data: MutableList<AdDeployData>): BaseResponse()

data class AdDeployData(var app: String = "", var appName: String = "", var token: String = "", var tokenStatus: Int = 0, var date: String = "", var type: Int = 0, var ids: String = "", var adPositions: String = "",var title: String = "",var viewType: Int = 1): Serializable


//詳情頁面

data class AppDetailResponse(var data: AppDetails):BaseResponse()

data class AppDetails(var app: String,var appName: String,var token: String,var tokenStatus: Int,var appDetails: MutableList<AppDetail>)

data class AppDetail(var adPlaceId: String,var app: String,var adStatus: Int,var serverId: Int,var sources: MutableList<Source>?):Serializable

data class Source(var id: String = "1",var packageName: String = "com.wifi.cool",var adPositionId: String = "1",var adCenterId: Int = 23,var level: Int =2,var centerName: String = "xxxx",var size: String = "RECT",var type: String = "DO"):Serializable

kotlin的基礎

kotlin基本數據類型:
類型 字寬
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

在 Kotlin 中,所有的類型都是一個引用類型。在java中,分為基本數據類型和引用數據類型,這里需要注意的是,這些類型的首字母都是大寫的

如何定義一個常量和變量
  1. 定義常量的關鍵字為val
val  a: Double = 27  //val + 變量名 +`:` + 空格+"類型" +" = " +"值"
val a = 27                //如果知道具體的類型,可以不帶類型,kotlin會自動類型推斷

注: a. 前面默認添加了public。

  1. 定義變量的關鍵字var
var name: String = "yhai"   //var + 變量名 +`:` + 空格+"類型" +" = " +"值"
var name = "yhai"              //如果知道具體的類型,可以不帶類型,kotlin會自動類型推斷

注意:
1.上面的空格是為了好的代碼格式

  1. 對于變量,如果需要延遲初始化,需要在var 前面添加lateinit關鍵字。延遲初始化后面還會詳細講解。
lateinit var name: String

name = "yhai"
  1. 使用var修飾的變量,實際上也就擁有了get和set方法,而val修飾的沒有set方法。
基本數據類型的轉換
val value0: Int  = 23
val value1: Long = value0.toLong()
val value2: Double = value0.toDouble()
val value3: Float = value0.toFloat()

kotlin中的基本數據類型轉換需要顯示的調用對應的方法

數組的定義

java

Object[] objects = new String[2];
objects[0] = "0";
objects[1] = "1";

kotlin

    var array: Array<Any>
    var strings: Array<Any> = arrayOf("1", "2")
    array = strings

kotlin中數組使用Array<TYPE> 定義。上面的Any是kotlin中的最根上的類,可以理解為跟java中的Object一樣。

字符串輸出
val value = "hello,world"
println("str ==  $value")

val person = Person()
println("str ==  ${person.age}")

在""中,使用$value就能把value給打印出來,如果person 是一個復雜的對象,需要使用${表達式}

kotlin中創建一個對象不需要使用new關鍵字
java kotlin
Persion person = new Person() val person: Persoin = Person()
val person = Person() 自動類型推斷

kotlin 中package 比較特殊,文件上的package 可以隨便定義,例如:

package com.xxx.xxx.xxx
class  Person{
}

而這個文件真實的路徑在com.yhai.kotlin目錄下,在導入包的時候,需要注意下,否者看到這個文件在某個目錄下,但是導入這個文件的包名并不是com.yhai.kotlin,而是com.xxx.xxx.xxx

控制流

if else
//傳統用法
var max = a
if (a < b)
max = b
//帶 else var max: Int if (a > b)
max = a
else
max = b
//作為表達式
val max = if (a > b) a else b

if 分支可以作為塊,最后一個表達是是該塊的值:

val max = if (a > b){
    print("Choose a")
    a
} else{
    print("Choose b")
b }

注:kotlin 的if判斷跟java里面的使用方式差不多,唯一不同的是可以作為一個表達式有返回值。

when

用法一

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { //Note the block
        print("x is neither 1 nor 2")
    }
}
 

or
    when (item.itemId) {
            R.id.nav_setting->{

            }
            R.id.nav_share -> {

            }
            R.id.nav_send -> {

            }
        }

用法一

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { //Note the block
        print("x is neither 1 nor 2")
    }
}
 

用法二

when (x) {
    0,1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}
 

用法三

when (x) {
    parseInt(s) -> print("s encode x")
    else -> print("s does not encode x")
}

用法四:作為表達式

val hasPrefix = when (x) {
    is String -> x.startsWith("prefix")
    else -> false
}
while
while (x > 0) {
    x--
}
do {
    val y = retrieveData()
} while (y != null) // y 在這是可見的
for
for(item in collection){
}

對于各種循環,如何正確的終止呢?
參考學習資料

類和對象

類的定義

定義一個類更java中一樣,使用class關鍵字。
第一種定義類的方式:沒有參數,沒有類體

class Person 

這樣就定義了一個Person類,定義的這個Person類實際上是沒有寫錯的。kotlin中如果這個類中沒有屬性,沒有方法(后面會講怎么跟這個類添加一個方法),類名后面的(){}就可以省略掉
第二種定義類的方式:有類體,沒有參數

class Person{
}

第三種種定義類的方式:有參數,有類體

class Person(var name: String,var age: Int){
  //TODO 做些事情
}

在使用java的時候,我們在構造函數中傳入參數,然后在構造函數體內做一些初始化的事情,而上面的構造函數的參數是直接跟在類名后面,在哪里做初始化的事情呢?實際上上面有個init{}代碼塊沒寫,完整的如下:

class Person(var name: String,var age: Int){
      init{
      //在這個位置做類似于java中構造函數體類做的事情。    
    }
}

這上面有個隱藏的知識點:

  1. 在構造函數中定義的參數使用var修飾,該參數將會在當前類全局都可以使用。不使用var修飾,那么該參數的使用范圍只會在init{}中。這個我是通過將kotlin編譯成.class,然后再翻譯成java代碼知道的。具體操作后面講。

第四中定義類的方式:有參數,沒有類體

class Person(val name: String,val age: Int)

如何定義多個構造函數:如果類有主構造函數,每個二級構造函數都要,或直接或間接通過另一個二級構造 函數代理主構造函數。在同一個類中代理另一個構造函數使用 this 關鍵字:

class Person(val name: String,val age: Int ) {
    init{
          //這里會是最后調用的地方
      }
    constructor (name: String,age: Int,var other: String) : this(name,age) {
    }
}

注:在上面第一種定義類的地方,存在一個默認的構造函數,這個構造函數是不帶參數的。

class Person(){
}
定義函數: 使用fun關鍵字,

格式: fun + 函數名+(參數列表)+"空格"+":" +"空格" 返回類型+{//函數體}

fun  dataIsModify(cache: List<String>,data: MutableList<String>) : Boolean{
    //...
    return false
}

注:1. 參數列表不能使用var 或val修飾,默認是有val修飾了。

  1. 空格是為了代碼格式
函數參數列表的默認值:

我們定義函數的時候,調用函數的時候,必須要傳入對應的參數,kotlin中,可以對參數列表設置默認的值,也就是說,有些參數可傳可不傳。

fun showDialogMessage(title: String = "", body: String = "this is a dialog") {
    //create a dialog 
}

調用上面這個函數:

showDialogMessage() //使用默認值
//或者只修改 body的值
showDialogMessage(body = "change dialog hint")//body 參數不使用默認值
繼承

<span id="jump">跳轉到的地方</span>
在kotlin中,類默認情況下是不能被繼承的,需要在定義類的前面加上open關鍵字,該類才能被繼承。同理,如果函數可以被繼承,也需要使用open修飾,默認不能被繼承。
繼承的語法:使用: + 被繼承的類名+(),()如果有參數的話,需要傳遞進去。

open class Base(var x: Int,var b: Int){
    open fun add() : Int{
        return x + b
    }
}
class Person(x: Int, b: Int) : Base(x,b){
}

注:在這里,Person類的構造中帶有兩個參數,沒有使用var或者val修飾,原因是父類已經定義了x,b兩個屬性。在Person中定義就沖突了。如果一定要使用varval修飾,需要改變參數名;

open class Base(var x: String,var b: Int)

class Person(var xx: String,var  bb: Int) : Base(xx,bb){
}

//這里我遇到一個類似的場景,我在后面講。
注: 如果要重寫Base中的方法,那么該方法需要用override修飾,表示是重寫的父類的方法。java中使用的是@override注解表示被重寫的方法。

class Person(x: Int, b: Int) : Base(x,b){
    override fun add(): Int {
        return super.add()
    }
}
抽象類的定義:

使用abstract 關鍵字修飾,跟java中一樣。同理,里面的抽象方法也需要abstract修飾。和java一樣,也可以定義具體的方法。

abstract class Derived  {
    abstract fun f()  
    
    fun f2(){   
    }
}
sealed修飾的密封類

類的定義中,有一種密封類的概念
密封類相關資料

類的屬性

之前有講到定義一個變量和一個常量的方法,他們的完整的語法如下:

var <propertyName>: <PropertyType> [ = <property_initializer> ]
    <getter>
    <setter>

如果屬性類型可以從初始化語 句或者類的成員函數中推斷出來,那么他的類型也是忽略的。
語法中的初始化語句,getter 和 setter 都是可選的,他們是什么意思呢?如下:

var name : String
    get() = name// 可以對獲取這個做一些修改。類似于java中的get方法體重做了一些事情。
    set(value) {
        //設置值做一些事情
    }
備用字段 或者叫做幕后字段 :field

這個概念的資料
我還沒有怎么使用,所以放個鏈接,自己去看。

空安全

是時候講下空安全是什么東西了。在kotln中,有一個很屌的功能,就是避免java中報null錯誤的處理方式。

var name: String = null  //語法不通過。必須對該屬性賦值,而且這個值不能是null

//這樣定義是語法檢查不過的,因為你對name賦值為null,那么如果你一定要讓這個name可以為null怎么做呢

var name: String? = null

//對,在類型String后面跟上一個?,大概意思是說,這個那么可以為空。
那么這個name使用的過程中,就有可能是個null,意味著要報null異常。為了防止報null,如下使用:

name?.toString()

在name上使用?. 調用它的方法。這樣就能保證使用name避免出現null異常。
如果你定義了一個變量,這個變量為null,你還是堅決要調用他,怎么辦呢?使用!!

   var name = null
    name!!.toString() // 這樣就必然會報null異常

這里只要記住,?的意思是說可能為空,在調用可能為空的時候,使用?.避免異常和使用!!為空也要調用。

kotlin中接口的定義

kotlin中的接口中可以定義方法體,跟抽象類一樣,這樣接口和抽象類就一樣了,我沒有搞懂什么意思!接口的定義還是使用interface關鍵字

interface MyInterface {
   val property: Int // abstract
   val propertyWithImplementation: String
       get() = "foo"
   fun foo() {
       print(property)
} }

接口的實現:

class Child : MyInterface {
    override val property: Int = 29
}

接口實現和基礎類的區別在于是有后面跟()

繼承一個類和實現多個接口:
class Base(){

}
interface  MyInterface0 {
    override val property: Int = 29
}
interface MyInterface1 {
     fun  test(){
    }
}
class Child : Base(), MyInterface0, MyInterface1 {

}

解決重寫沖突

多個接口中有相同的方法
在文檔中直接copy的代碼如下:

interface A {
    fun foo() { print("A") }
    fun bar() 
}
interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}
class C : A {
    override fun bar() { print("bar") }
}
class D : A, B {
    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    }
}

可見性修飾詞

在 Kotlin 中有四種修飾:private,protected,internal,以及public,默認的為public。

private 只在該類(以及它的成員)中可見

protected 和 private 一樣但在子類中也可見

internal 在本模塊的所有可以訪問到聲明區域的均可以訪問該類的所有成員 ( internal — any client inside this module who sees the declaring class sees its internal members;)

public 任何地方可見 (public — any client who sees the declaring class sees its public members.)

伴隨對象

這個相當于java中的static 修飾的方法和屬性.因為kotlin沒有static關鍵字,實現靜態方法的方式如下:在***companion object{} ***中de {}定義方法和屬性就可以。

class Person7{
    companion object{
        var name = ""
        fun test(){  
        }
    }
}
Person7.test()//使用方式
擴展方法和屬性和伴隨對象的擴展

關于屬性的擴展沒怎么搞懂,下面不講,項目中我暫時也沒有用到。
在類定義的第一種定義方法中,定義了如下一個類

class Person

顯然,定義了這么一個類是沒有什么實際用途的。我們使用kotlin的擴展extension特性對其擴展一些方法。也就是說,我可以給所有的類添加方法。實現方式如下:

擴在函數格式:fun + "要對擴展的類的名字" + "."+方法名()+ "{} //方法體"
fun Person.eat(name: String){
    System.out.println("吃的是什么 = $name")
}

這樣Person這個類就已經有了一個叫做eat(name: String)方法了。

伴隨對象的擴展

格式:fun +類名+"."+"Companion"+"."+"方法名"+"(參數列表)"+"{}"

fun Person7.Companion.test2(){

}
數據對象

java中有個javaBean的概念,在kotlin中有自己的定義方法使用data修飾的的class類

data class Source(var id: String = "1",var packageName: String = "com.wifi.cool",var adPositionId: String = "1",var adCenterId: Int = 23,var level: Int =2,var centerName: String = "xxxx",var size: String = "RECT",var type: String = "DO"): Serializable

上面有如下幾個特點:

  1. 參數需要有var或val修飾,可以轉換成java代碼對比。
  2. 參數有默認值
  3. 實現了Serializable接口
內部類

類可以標記為 inner 這樣就可以訪問外部類的成員。內部類擁有外部類的一個對象 引用:

class Outer {
    private val bar: Int = 1
    inner class Inner {
        fun foo(): Int{ return bar}
    }
}

匿名內部類

使用object關鍵字

window.addMouseListener(object: MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
// ...
}
    override fun mouseEntered(e: MouseEvent) {
        // ...
} })
代理屬性

代理屬性的意思我理解為你的屬性交給我來管理。什么意思呢?

class User(){
var name: String  = ""
var age: Int = 23
}
val  user = User()
user.name = "yhai"
user.age = 27

上面這個User對象的name和age屬性的值發生改變時,我要把這個值通過SharePerference存著本地。那我就可以把這個屬性代理起來,保存在本地的這個事情就在這個代理類中實現。這個類需要繼承ReadWriteProperty<Any?, T>類。下面這個代理類是用來操作sp的。


import android.content.Context
import manage.ad.yiba.com.admanage.App
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/**
 * Created by yh on 8/25/17.
 */
class Preference<T>(context: Context = App.instance, val name: String?, val default: T) : ReadWriteProperty<Any?, T> {

    val prefs by lazy {
       context.getSharedPreferences("yiba",Context.MODE_PRIVATE)
    }
    override fun getValue(thisRef: Any?, property: KProperty<*>): T = with(prefs){
        when (default) {
            is Long -> {
                getLong(name, default)
            }
            is String -> {
                getString(name, default)
            }
            is Float -> {
                getFloat(name, default)
            }
            is Int -> {
                getInt(name, default)
            }
            is Boolean -> {
                getBoolean(name, default)
            }
            else -> {
                throw IllegalArgumentException("This type can be saved into Preferences")
            }
        } as T
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = with(prefs.edit()){
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Float -> putFloat(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            else -> {
                throw  IllegalArgumentException("存儲的類型不存在,請確認儲存類型")
            }
        }.apply()
    }

}

實際上就是代理這個屬性的get和set方法。
上面有兩個東西沒有提到:

  1. is 相當于java中的instanceof
  2. as 相當于java的強制,例如:
    java
TextView  tv = (TextView)findViewById(id);

kotlin

TextView  tv =findViewById(id) as TextView
  1. with(obj) 相當于在obj的內部。
val user = User()
with(user){
  //在這里可以直接操作User的屬性和方法。而不需要user.name或者user.eat("xxxx"),省略user.
}
函數

之前對已經講了怎么定義一個函數,但是在kotlin中函數作為一等公民,顯示還有很多高級的用法。
1.單表達式函數
當函數只返回單個表達式時,大括號可以省略并在 = 后面定義函數體

fun test(){
return  23
}

可以寫成下面

fun test() =23
中綴符號

在滿足以下條件時,函數也可以通過中綴符號進行調用:
它們是成員函數或者是擴展函數 只有一個參數 使用 infix 關鍵詞進行標 記

//給 Int 定義一個擴展方法
infix fun Int.shl(x: Int): Int { ...
}
1 shl 2 //用中綴注解調用擴展函數 
1.shl(2)

這個在我第一次看的時候,感覺屌爆了。

默認參數
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size() ) {
...
}

注:函數如果沒有返回值的時候是一個Unit類型,默認可以不寫,例如上面的函數也可以寫成

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size() )  : Unit{
...
}
變長參數
fun asList<T>(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts)
        result.add(t)
    return result
}

使用如下:

 val list = asList(1, 2, 3)

java中使用的是...表示可變參數,kotlin中使用的是vararg。

函數內部定義函數

什么優缺點現在我也沒有搞懂。

fun dfs(graph: Graph) {
    val visited = HashSet<Vertex>()
    fun dfs(current: Vertex) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
dfs(v) }
    dfs(graph.vertices[0])
}
函數可以賦值給另一個函數
//定義了一類
class Person6
//給該類擴展了一個方法
fun Person6.eat(name: String){

}
//創建Person6的對象
val v = Person6()
//將v.eat(xxx: String)賦值給另一個函數
fun test(xx: String) = v.eat(xx)

閉包

private val value = {xx: String,bb: String->Unit

}

上面的代碼,定義了一個閉包,并且把這個閉包賦值給了一個value的變量。
怎么使用它了,有兩種方式:

//第一種方法使用invoke,后面括號是參數
value.invoke("value0","value1")
//第二種方法類似于函數的調用
value("value0","value1")

閉包實際上就是一個使用{}包起來的代碼塊,在上面這個閉包中,->左邊是閉包的參數列表,右邊是返回類型。在閉包的最后一行作為默認的返回值。

{xx: String,bb: String->Unit
  {
   //閉包體
  }
}

閉包可以作為一個函數的參數如下:
test方法有一個閉包作為參數,這個閉包的參數列表為空,返回值為Unit

fun test(code: ()->Unit){
    code.invoke()
}
//調用寫成下面這樣
val clourse = { 

}
test(clourse)
 //在可以寫成
test({})
//如果一個函數的參數只有一個閉包參數可以省略()
test{xx: String ->{
  }
}

//這個閉包體可以省略,這個以閉包作為參數的函數可以寫成下面這樣。
test{
}

自定義dsl

這個知識點不理解不影響android的開發
在我們的gradle中,有類型與下面的代碼,他是怎么實現的呢?

  email{
        address = "1454025171@qq.com"

        baseInfo()
        from("this is  from")
        to("this is to fun")
        body{
            p("this is body fun")
        }

    }

dsl代碼實現

下面這段代碼是網上的一個哥們實現的,我忘了保存其地址!!


class EmailSpec{
    var address: String  = ""

    fun baseInfo() = println("address = $address")
    fun from(from: String) = println("From: $from")
    fun to(to: String) = println("To: $to")
    fun subject(subject: String) = println("Subject: $subject")
    fun body(init: BodySpec.() -> Unit): BodySpec { //這個方法的參數為一個函數,該參數函數返回Unit。該方法返回BodySpec
        val body = BodySpec()
        body.init()
        return body
    }
}


class BodySpec {
    fun p(p: String) = println("P: $p")
}

/**
 * 1. 定義一個方法函數作為參數的方法
 * 2. 對EmailSpec 擴展了一個方法,該方法沒有參數,沒有返回值;目的是可以調用內部的其他方法
 * 3. 該方法返回一個EmailSpec 的對象
 *
 */

fun email(init: EmailSpec.()->Unit) {
    val email = EmailSpec() //創建一個對象
    email.init()
    //調用的是參數中定義的init函數,不是系統的init函數
}

上面這個dsl理解了email這個方法,就理解了怎么定義dsl。
首先定義一個反復,這個方法有一個參數,這個參數是對EmailSpec類擴展了一個空函數,返回值也為空。在這個email方法的體中,創建了EmailSpec的實例,然后這個實例調用了這個擴展方法。EmailSpec.()->Unit 這個擴展方法是在方法中定義的,所以他的范圍也只在這個email方法內部區域。

關于操作符的使用

關于操作符,有點想Rxjava里面的操作符的用法。
關于操作符的使用

那些東西沒有說:
對象表達式和聲明,代理類,異常,this表達式,運算符重載 ...

kotlin與java的對比

copy的內容

java 有的而 kotlin 沒有

異常檢查
原始類型不是類
靜態成員
非私有成員
通配符類型

kotlin 有的而 java 沒有

字面函數+內聯函數=高性能自定義控制結構 擴展函數 空安全 智能轉換 String 模板 性能 一級構造函數 First-class delegation 變量和屬性類型的類型接口 單 例模式 變量推斷和類型預測 范圍表達式 運算符重載 伴隨對象

本來準備一次性寫完,太累了,分成兩篇來寫!!!下一篇將如何寫一個android項目,如果你有使用java開發android經驗,那將會是非常的容易。
下一篇將如下類容

kotlin 開發android項目的相關經驗

anko相關的知識點 布局和其他
網絡請求
基礎類的擴展
定義組合式控件
點擊事件,

kotlin 語法相關資料

kotlin 官方原文資料

在學習go語言的時候,有多返回值,在kotlin中,可能用解構聲明比較
解構聲明

關于操作符的使用

kotlin for android

kotlin for android

kotlin 資料大全

kotlin基礎資料

什么是內聯函數

kotlin和java的對比文檔

關于dsl的資料

這篇文章讓我讀出了閉包的味道,Kotlin語法基礎,函數與閉包

//閉包也是函數,是一個可以讀取其他函數內部變量的函數。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容