函数

一级公民

可单独声明在文件中,不依赖于类、接口等

单表达式

fun log(s: String) = Logger.d(s)
fun add(i: Int) = i + 1

默认参数

fun test(s: String, bool: Boolean = false, i: Int = 1, f: Float = 1f) {}

test("tag")
test("tag", f = 100f)
test(s = "tag", bool = true, i = 100, f = 100f)

局部函数

fun func() {
    fun add(i: Int) = i + 1
    val a = add(100)
}

扩展函数

  1. 未改变类,只给对象添加方法

    fun MutableList<Int>.swap(index1: Int, index2: Int) {
        val tmp = this[index1] //this是对象本身
        this[index1] = this[index2]
        this[index2] = tmp
    }
    
    val list = mutableListOf(1, 2, 3)
    list.swap(0, 1)
    
  2. 和成员函数重名,调用成员函数

  3. 区别成员函数

    open class A
    class B : A()
    fun A.log()  = Logger.e("A.log")
    fun B.log()  = Logger.e("B.log")
    
    fun log(a: A) = a.log()
    val a = A()
    val b = B()
    log(a) //输出 A.log
    log(b) //也输出 A.log
    

扩展属性

var String.xxx: Int
        get() = length
        set(value) {
            println(value)
        }

中缀符

函数只有一个参数时可使用关键字infix标记

infix fun Int.shl(x: Int): Int { ... }
val a = 1.shl(20)
val b = 1 shl 20

for (i in 0..100 - 1)
for (i in 0 until 100)

val map = mapOf("age" to 100, "name".to("victor"))

inline & reified

refied使支持类型参数具体化

inline fun <reified T> parse(json: String) = Gson().fromJson(json, T::class.java)

val bean = parse<Bean>(json)

Lambda

val sum: (Int, Int) -> Int = { x, y -> x + y }
val log: (text: String) -> Unit = { Logger.d(it) } //只有一个参数可以用it代替

替换单方法接口

java
interface MyInterface {
    void log(String tag, String text);
}

private MyInterface myInterface;

public void setMyInterface(MyInterface myInterface) {
    this.myInterface = myInterface;
}

setMyInterface(new MyInterface() {
    @Override
    public void log(String tag, String text) {
        Logger.d(tag + ":" + text);
    }
});

public void doSth() {
    if (myInterface != null) {
        myInterface.log("tag", "content");
    }
}
kotlin
private var block: ((String, String) -> Unit)? = null

fun setBlock(param: (String, String) -> Unit) {
    block = param
}

setBlock { tag, text -> Logger.d("$tag:$text") }

fun doSth() = block?.invoke("tag", "content")

其它

Lambda最后一行作为返回值
val create: (tag: String, text: String) -> String = { tag, text ->
    val str = "tag:$tag text:$text"
    print(str)
    str
}
val str = create("tag", "text")
无用参数用_代替
setBlock { _, text -> Logger.d("$text") }
方法中作为最后一个参数可放在括号外,单参数可不写括号
fun set(number: Int, block: (String) -> Unit) = block(number.toString())
fun set(block: (String) -> Unit) = block("123")

set(1, { Logger.d(it) })
set(1) { Logger.d(it) }
set{ Logger.d(it) }

DSL

() -> Unit		//无参数Lambda
(T) -> Unit		//单参数,类型是T,block中可用it表示T对象
T.() -> Unit	//无参数Lambda,block中可操作T对象的属性和方法
未使用dsl
httpPost(HttpApi.GET_RTMP, obj, object : HttpUtil.CallBack {
    override fun onSuccess(json: String?) {
        view.getRtmpSucceed(json)
    }
  
    override fun onFailure(reason: String?) {
        view.showToast(reason)
    }
})
使用dsl
http {
    url = HttpApi.GET_RTMP
    body = obj
    success = { view.getRtmpSucceed(it) }
    fail = { view.showToast(it) }
}
实现
class Http {
    lateinit var url: String
    var body: JsonObject? = null
    var success: ((json: String?) -> Unit)? = null
    var fail: ((reason: String?) -> Unit)? = null
}

fun http(block: Http.() -> Unit) {
    val h = Http().apply { block() }
    ...
}

//类似的实现: Anko, html构造器
html(lang:'en') {                                                                   
    head {                                                                          
        meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"')      
        title('My page')                                                            
    }                                                                               
    body {                                                                          
        p('This is an example of HTML contents')
      	h1("This is title")
    }                                                                               
}   

常用的自带扩展函数

inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
apply: block里操作方法和属性,最后返回自身
val array = arrayOfNulls<Int>(10).apply { 
  fill(0) 
  println("fill array")
}
fun setTitle(title: String) = apply { this.title = title }
//等价于
fun setTitle(title: String): Builder {
    this.title = title
    return this
}
with: block里操作方法和属性,返回值为最后一行

Control类控制上下左右

with(control) {
    up()
    down()
    left()
    right()
}

判空操作

  1. java
    if (myInterface != null) {
        myInterface.log("tag", "content");
    }
    if (myInterface != null) {
        Logger.d("myInterface")
    }
    
    kotlin
    myInterface?.invoke("tag", "content")
    myInterface?.let { Logger.d("myInterface") }
    
  2. java
    private String test(Bean bean) {
        return bean == null ? "null" : bean.getMsg();
    }
    
    kotlin
    private fun test(bean: Bean?) = if (bean == null) "null" else bean.msg
    private fun test(bean: Bean?) = bean?.msg ?: "null"
    
    //类似的
    val i = "100".toIntOrNull() ?: 0
    val str = any as? String ?: "null"
    

typealias

typealias MyType = (Int) -> Boolean
fun test(type: MyType) {}

typealias MyList<T> = java.util.ArrayList<T>
val list = MyList<String>()

JvmPlatformAnnatations

JvmOverloads kotlin有默认值的函数在java中显示为重载函数

JvmStatic java调kotlin object方法时不需写INSTANCE

类相关

属性

懒加载
private val str by lazy { "lazy" }
延迟初始化
private lateinit var str: String
private var str: String by Delegates.notNull()

单例

object替代class

object Singleton

类代理

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() = println(x)
}

class Derived(b: Base) : Base by b

fun test() {
    val impl = BaseImpl(10)
    Derived(impl).print()
}

多重声明

for ((key, value) in map) {}

data class Result(val code: Int, val status: String)

val (code, status) = result
val (_, status) = result

其它语法

数字分隔

val n = 10_000_000
val n = 0x00_00_00_01

展开

fun test(vararg numbers: Int) {}

val array = intArrayOf(2,3,4)
test(1, *array, 5)

转换

java
int a = 0
Integer b = 0;
int[] array1 = new int[]{1, 2, 3};
Integer[] array2 = new Integer[]{1, 2, 3};
kotlin
val a: Int = 0
val b: Int? = 0
val array1 = intArrayOf(1, 2, 3) //类型为IntArray
val array2 = arrayOf(1, 2, 3)  //类型为Array<Int>

强行实现三目运算符

java
int a = i > 0 ? i : 0
kotlin
infix fun <T> Boolean.yes(trueValue: () -> T) = TernaryOperator(trueValue, this)
class TernaryOperator<out T>(val trueValue: () -> T, val bool: Boolean)
infix inline fun <T> TernaryOperator<T>.no(falseValue: () -> T) = if (bool) trueValue() else falseValue()

val a = (i > 0).yes{i}.no{0}
val a = (i > 0) yes{i} no{0}

集合操作符 类似RxJava

list.filter { it.isNotEmpty() }
        .take(5)
        .map { it }
        .sortedBy { it }
        .onEach { Logger.d(it) }
        ...
        .forEach { Logger.d(it) }

协程

Coroutines are experimental in Kotlin 1.1, which means that it may be changed in the upcoming releases.