函数
一级公民
可单独声明在文件中,不依赖于类、接口等
单表达式
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)
}
扩展函数
-
未改变类,只给对象添加方法
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)
-
和成员函数重名,调用成员函数
-
区别成员函数
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()
}
判空操作
-
java
if (myInterface != null) { myInterface.log("tag", "content"); } if (myInterface != null) { Logger.d("myInterface") }
kotlin
myInterface?.invoke("tag", "content") myInterface?.let { Logger.d("myInterface") }
-
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.