Updated on 2017-04-13

https://kotlin.link/

https://kotlinlang.org/

https://devdocs.io/kotlin-reference/

https://kotlinlang.org/docs/reference/idioms.html

https://kotlinlang.org/docs/reference/basic-syntax.html

https://kotlinlang.org/api/latest/jvm/stdlib/index.html

https://try.kotlinlang.org/

https://kotlinlang.org/docs/kotlin-docs.pdf

https://github.com/JetBrains/kotlin/releases/latest

https://jcenter.bintray.com/org/jetbrains/kotlin/kotlin-stdlib/

https://storage.googleapis.com/developers-playground/kp-wrapper-devsite.html

Code

// ABC

/* DEF
   GHI */

-------------------------------------------------------

fun main(args: Array<String>) {     main 函数程序入口
    println("Hello World!")
}

-------------------------------------------------------

val a: String     先声明后赋值只适用于变量没有赋值时必须显式声明类型作为属性时必须在声明的同时进行赋值
a = "ABC"
----
val a: String = "ABC"     声明对象的同时进行实例化显式声明类型
----
val a = "ABC"     声明对象的同时进行实例化自动推导类型

-------------------------------------------------------
Kotlin 中没有Primitive基本数据类型一切皆为Reference引用数据类型

var a = 123     变量引用可变 get/set
val b = 123     常量引用只读 get

-------------------------------------------------------

val a = """     原始字符串
fun helloWorld(val name : String) {
   println("Hello, world!")
}
"""

----

val a = "ABC"
val b = "$a 的长度为${a.length}"     字符串模板

-------------------------------------------------------
Kotlin 中尽量将变量声明为不可空不可变

var a: String = null     编译器报错不可空变量
var b: String? = null     通过 `?` 明确标识变量可为 null可空变量

println(b.length)     编译器报错不能直接访问可空变量
println(b?.length)     通过 `?.` 访问可空变量若为 null则停止继续调用
println(b!!.length)     通过 `!!.` 访问可空变量若为 null则抛出 KotlinNullPointerException 异常

try {     try-catch
    println(b!!.length)
} catch (e: KotlinNullPointerException) {
    println("发生空指针异常!")
}

----

val a: String? = null

val b: Int = if (a != null) {     空检查
    a.length     不需要通过 `?.` 访问可空变量Smart Cast
} else {
    -1
}
可简化为
val c: Int = if (a != null) a.length else -1     可用于替代 Java 中的三元运算符
可简化为
val d: Int = a?.length ?: -1     `?:` 操作符若左边表达式的返回值为 null 则执行右边表达式

-------------------------------------------------------

fun sum(x: Int = 1, y: Int = 1): Unit {     函数设置参数默认值以减少重载
    println("$x+$y=${x + y}")     字符串模板
}
可简化为
fun sum(x: Int = 1, y: Int = 1) {     若返回值为 Unit (void)则可省略返回值
    println("$x+$y=${x + y}")
}
可简化为
fun sum(x: Int = 1, y: Int = 1) = println("$x+$y=${x + y}")     若函数体只含有 1 句表达式则可省略函数体和返回值自动推导类型

sum()
sum(3)
sum(y = 3)     命名参数
----
输出
1+1=2
3+1=4
1+3=4

-------------------------------------------------------

fun hello(name: String): String {
    return "Hello,$name"
}
可简化为
fun hello(name: String) = "Hello,$name"     若函数体只含有 1 句表达式可省略函数体和返回值自动推导类型

-------------------------------------------------------

fun show(vararg str: String): Unit {     vararg可变长参数参数数量 [0,)视为数组 Array<out T>
    for (s in str) {     str 为 Array<out String>
        print(s + " ")
    }
}

show()
----
输出

val array: Array<String> = arrayOf("B", "C")
show("A", *array, "D")     spread展开操作符在数组前加上 `*`
----
输出
A B C D
fun a(x: Int): Boolean {
    return x % 2 == 0
}
可简化为
fun a(x: Int) = x % 2 == 0     函数类型(Int) -> Boolean需要 Int返回 Boolean

@kotlin.internal.InlineOnly
public inline fun println(message: Int) {     函数类型(Int) -> Unit需要 Int返回 Unit)(类库自带函数
    System.out.println(message)
}

val array = arrayOf(1, 2, 3, 4)

array     使用 Lambda 表达式
    .filter { it % 2 == 0 }
    .forEach { System.out.println(it) }
等同于
array     使用函数引用
    .filter(::a)
    .forEach(::println)
等同于
val aa: (Int) -> Boolean = ::a     将函数引用存储在变量中类型声明"函数类型"
val bb: (Int) -> Unit = ::println
array
    .filter(aa)
    .forEach(bb)
----
输出
2
4

-------------------------------------------------------
高阶函数一种将函数作为参数或者返回值的函数
     函数参数
             Lambda 表达式跟 Java8 中的概念相同只能作为高阶函数的参数或返回值
             匿名函数没名字的函数只能作为高阶函数的参数或返回值
             命名函数可以通过函数引用作为高阶函数的参数
                     函数引用通过在函数名称前加上 `::` 操作符把命名函数作为参数传入

val array: Array<Char> = arrayOf('A', 'B', 'C', 'D')

val list: MutableList<Int> = array.mapTo(mutableListOf(), { c -> c.toInt() })     mapTo 为高阶函数{} 为 Lambda 表达式
可简化为
val list: MutableList<Int> = array.mapTo(mutableListOf()) { c -> c.toInt() }     高阶函数中若最后一个参数是函数参数可移至括号外若只需要一个函数参数可省略括号
可简化为
val list: MutableList<Int> = array.mapTo(mutableListOf()) { it.toInt() }     Lambda 表达式中若只接收一个参数可用 `it` 替代
可简化为
val list: MutableList<Int> = array.mapTo(mutableListOf(), Char::toInt)     Lambda 表达式转为函数引用

println(list)
----
输出
[65, 66, 67, 68]

-------------------------------------------------------

(1..5).reduce { _, _ -> 0 }     0若不需要 Lambda 表达式中提供的参数可用 `_` 占位

-------------------------------------------------------

fun a(i: Int): Int {
    return i * 2
}
可简化为
fun a(i: Int) = i * 2     命名函数有名字的函数

val list = listOf(1, 2, 3, 4, 5)

list.map(fun(i: Int): Int {
    return i * 2
})
可简化为
list.map(fun(i: Int) = i * 2)     匿名函数没名字的函数
----
list.map(::a)     对命名函数使用函数引用
----
list.map { it * 2 }     Lambda 表达式

-------------------------------------------------------

val list = listOf(1, 2, 3, 4, 5)

list.map({ i -> i * 2 })     此高阶函数只需要一个函数参数
可简化为
list.map() { i -> i * 2 }     移至括号外
可简化为
list.map { i -> i * 2 }     省略括号
可简化为
list.map { it * 2 }     使用 `it` 替代

-------------------------------------------------------
无标签限制的 this 指向包含当前代码的最内层

val stringBuilder = StringBuilder("123").apply a@ {     在 Lambda 表达式处显式声明标签以区分重名标签和 this 对象
    println(this@a)
    "456".apply {
        println(this@apply)
        this@a.append(this@apply)
    }
}
println(stringBuilder)
----
输出
123
456
123456

-------------------------------------------------------
有标签限制的 break 跳转至该标签指定的循环继续后面的表达式
有标签限制的 continue 跳转至该标签指定的循环继续下一次迭代

a@ for (x in 0..9) {
    b@ for (y in 10..19) {
        if (x == 5 && y == 15) {
            break@a     跳转至最外层循环并结束最后输出5 14
        }
        println("$x $y")
    }
}

-------------------------------------------------------
无标签限制的 return 返回结果至最直接包含它的函数
带标签限制的 return 一般应用于高阶函数中的 Lambda 表达式

Lambda 表达式会形成一个闭包捕捉使用到的外部变量形成一个作用域),可以通过 Inline消除这种开销
对象是带方法的数据
闭包是带数据的方法。(Closure

inline 签名一般与高阶函数搭配使用以优化 Lambda 表达式直接将代码写至调用处来减少函数调用栈的层数会增加代码生成量

Kotlin 类库中的大部分高阶扩展函数都带有 inline 签名使其成为内联高阶扩展函数导致 Lambda 表达式不会引入
新作用域函数体中的变量和外部环境中的变量具有相同的语义

fun main(args: Array<String>) {
    a()
    println("————————————")
    b()
    println("————————————")
    c()
}
fun a() {
    val list1 = listOf(1, 2, 3, 4)
    println(list1)
    val list2 = list1.filter {     Lambda 表达式无标签限制返回结果至 fun a()最直接包含此 Lambda 表达式的函数
        print("+ ")
        it % 2 == 0
        return
    }
    println()
    println(list2)
}
fun b() {
    val list1 = listOf(1, 2, 3, 4)
    println(list1)
    val list2 = list1.filter {     Lambda 表达式有标签限制返回结果至 filter
        print("+ ")
        return@filter it % 2 == 0     隐式标签与接收该 Lambda 表达式的高阶函数同名
    }
    println()
    println(list2)
}
fun c() {
    val list1 = listOf(1, 2, 3, 4)
    println(list1)
    val list2 = list1.filter(fun(i: Int): Boolean {     匿名函数返回结果至 filter
        print("+ ")
        return i % 2 == 0
    })
    println()
    println(list2)
}
----
输出
[1, 2, 3, 4]
+
————————————
[1, 2, 3, 4]
+ + + +
[2, 4]
————————————
[1, 2, 3, 4]
+ + + +
[2, 4]

-------------------------------------------------------

fun main(args: Array<String>) {
    print(1)
    a {     未内联高阶函数return1 个选项返回结果至 a
        print(2)
        return@a     隐式标签与接收该 Lambda 表达式的高阶函数同名
    }
    print(3)
    ----
    输出
    123

    print(1)
    b {     已内联高阶函数return2 个选项返回结果至 b带标签 或 main不带标签)(最直接包含此 Lambda 表达式的函数
        print(2)
        return
    }
    print(3)
    ----
    输出
    12

    print(1)
    b {     已内联高阶函数
        print(2)
        return@b     隐式标签与接收该 Lambda 表达式的高阶函数同名
    }
    print(3)
    ----
    输出
    123
}

fun a(block: () -> Unit) {     未内联高阶函数
    block()
}

inline fun b(block: () -> Unit) {     已内联高阶函数
    block()
}

-------------------------------------------------------
注意 inline 修饰函数crossinlinenoinline 修饰函数参数

inline fun a1(block: () -> Unit) {
    block()     作为函数调用
}

inline fun a2(crossinline block: () -> Unit) {     可以通过 crossinline 修饰函数参数交叉内联此函数参数
    thread { block() }     作为函数调用
    等同于
    thread(block = { block() })     移至括号内并命名参数
}

inline fun x(block: () -> Unit) {
    thread(block = block)     编译器报错不能将内联函数作为参数传入
}

inline fun b(noinline block: () -> Unit) {     可以通过 noinline 修饰函数参数取消内联此函数参数从而可以作为参数传入inline 签名就没起到作用了
    thread(block = block)     作为普通参数传入
}
data class A(val id: Int, val name: String) : Closeable {     数据类自动生成 hashCodeequalstoStringcopy 函数
    override fun close() {
        println("close!")
    }
}

val a = A(1, "小明")     实例化对象
val b = a.copy(name = "小张")     copy 函数深度复制
val (x, y) = a     解构声明component 函数

println("$x $y")     字符串模板
println(a)
println(b)
----
输出
1 小明
A(id=1, name=小明)
A(id=1, name=小张)

-------------------------------------------------------

with(a) {     高阶函数
    println("[${this.id}, ${this.name}]")
}
----
输出
[1, 小明]

-------------------------------------------------------

a.use {     由于主动继承自 Closeable所以能够使用 use 高阶函数Closeable 接口的扩展函数用于替代 Java7 的 ARM
    println("[${it.id}, ${it.name}]")
}
----
输出
[1, 小明]
close!
val list = listOf("A", "B", "C")     生成不可变 List元素不可被添加或删除只读
val set = setOf("A", "B", "C")     生成不可变 Set
val map = mapOf("A" to 0, "B" to 1, "C" to 2)     生成不可变 MapKotlin 中的 Map 存储的是 Pair
val mutableList = mutableListOf("A", "B", "C")     生成可变 List

println(list[0])
println(set.contains("A"))
println(map["A"])
----
输出
A
true
0

for ((k, v) in map) {     解构声明Kotlin 中的 Map 存储的是 Pair
    println("$k -> $v")
}
----
输出
A -> 0
B -> 1
C -> 2

-------------------------------------------------------

val list = listOf('A', 'B', 'C')

list.asIterable()     Iterable急性求值Eager)(多用于小型集合)(默认
        .filter {
            println("filter:$it")
            true
        }
        .map {
            println("map:$it")
            it.toInt()
        }
        .first().let(::println)
----
输出
filterA
filterB
filterC
mapA
mapB
mapC
65

list.asSequence()     Sequence惰性求值Lazy)(多用于大型集合)(类似于 Java8 中的数据流
        .filter {
            println("filter:$it")
            true
        }
        .map {
            println("map:$it")
            it.toInt()
        }
        .first().let(::println)
----
输出
filterA
mapA
65

-------------------------------------------------------

val map: Map<String, List<Int>> = (1..9)
        .map { it * 3 }     映射
        .filter { it < 20 }     过滤
        .groupBy { it % 2 == 0 }     分组
        .mapKeys {     映射
            if (it.key) {
                "偶数"
            } else {
                "奇数"
            }
        }
println(map)
----
输出
{奇数=[3, 9, 15], 偶数=[6, 12, 18]}

-------------------------------------------------------

val list1 = listOf(1..3, 4..6)     [1..3, 4..6]
val list2 = list1.flatMap { it }     [1, 2, 3, 4, 5, 6]     平铺
val list3 = list2.map { it * 2 }     [2, 4, 6, 8, 10, 12]     映射

-------------------------------------------------------

val intRange = 1..4
val i = intRange.reduce { acc, i -> acc + i }     10不带初始值
val j = intRange.fold(-5) { acc, i -> acc + i }     5带有初始值

-------------------------------------------------------

val intRange = 1..10
val list = intRange.takeWhile { it % 5 != 0 }     [1, 2, 3, 4]一直获取直到元素不符合条件为止

-------------------------------------------------------

val list: List<Any> = listOf("A", "B", "C", 1, 2, 3, 4)
list.filter { it is Int && it % 2 != 0 }.forEach(::println)
                   判断类型    自动转型Smart Cast   函数引用
----
输出
1
3
for
val intRange: IntRange = 1..5     范围表达式
for (i in intRange) {
    print("$i ")
}
可简化为
for (i in 1..5) {     1 2 3 4 5     全包含
    print("$i ")
}

for (i in 1 until 5) {     1 2 3 4     半包含
    print("$i ")
}

for (i in 2..10 step 2) {     2 4 6 8 10     步长
    print("$i ")
}

for (i in 10 downTo 5) {     10 9 8 7 6 5     降序
    print("$i ")
}

for (c in "Hello") {
    println(c)
}

if (i in 1..10) {
    println("YES")
} else {
    println("NO")
}

遍历对象并带有索引位置
----
val strs = arrayOf("A", "B", "C")
for ((index, s) in strs.withIndex()) {     对 IndexedValue<T> 的解构声明
    println("$index -> $s")
}
strs.forEachIndexed { index, s ->
    println("$index -> $s")
}
----
输出
0 -> A
1 -> B
2 -> C
0 -> A
1 -> B
2 -> C

-------------------------------------------------------

whiledo...while
var i = 0
while (i < 5) {
    println(i)
    i++
}
do {
    println(i)
    i++
} while (i < 10)
----
输出
0
1
2
3
4
5
6
7
8
9

-------------------------------------------------------
when和所有分支条件进行顺序比较用于替代 Java 中的 switch):

val i = 8
when (i) {     提供参数匹配对应参数类型替代 switch
    0, 21 -> println("0 or 21")
    in 1..20 -> println("1 to 20")     在
    !in 22..100 -> print("x<0 or x>100")     不在
    is Int -> print("is Int")     是Smart Cast
    !is Int -> print("not Int")     不是
    else -> println("other")
}
when {     不提供参数匹配布尔类型可替代 if-else if    i < 5 -> println("first block")
    i < 10 -> println("second block")
    else -> println("else block")
}

-------------------------------------------------------
流程控制语句可作为表达式提供返回值

val s = if (Math.random() - Math.random() > 0) {
    "成功"
} else {
    "失败"
}
可简化为
val s = if (Math.random() - Math.random() > 0) "成功" else "失败"     替代三元运算符

val s2 = when (Math.random() - Math.random() > 0) {
    true -> "成功"
    false -> "失败"
    else -> "失败"
}

-------------------------------------------------------

fun smartCast(x: Any): Boolean {     自动类型转换智能转型
    if (x is Boolean) {     通过类型检查后自动转换类型
        return x
    } else if (x is Int) {
        return x > 0
    } else if (x is String) {
        return x.startsWith("Hello")
    } else {
        return false
    }
}
可简化为
fun smartCast(x: Any): Boolean {     用 when 替代 if-else if    when (x) {
        is Boolean -> return x
        is Int -> return x > 0
        is String -> return x.startsWith("Hello")
        else -> return false
    }
}
可简化为
fun smartCast(x: Any): Boolean {     用 when 作为返回值
    return when (x) {
        is Boolean -> x
        is Int -> x > 0
        is String -> x.startsWith("Hello")
        else -> false
    }
}
可简化为
fun smartCast(x: Any) = when (x) {     简化表达式省略函数体和返回值
    is Boolean -> x
    is Int -> x > 0
    is String -> x.startsWith("Hello")
    else -> false
}
val any: Any = "ABC" as Any     强制类型转换若转换失败则抛出异常 java.lang.ClassCastException
----
if (any is String) {     等同于 instanceof若通过检查则在代码块中进行智能转型Smart Cast
    println(any.length)     类型String
}
println(any.length)     类型Any无 length 属性报错

-------------------------------------------------------

fun String.abc(c: Char): String {     扩展函数给一个类添加新的功能
    return this.filter { it != c }     false 过滤true 不过滤
}
可简化为
fun String.abc(c: Char) = this.filter { it != c }

println("Hello".abc('l'))
----
输出
Heo

fun String.Companion.abc() {     静态扩展函数给一个类的伴生对象添加新的功能
    println("ABC")
}
可简化为
fun String.Companion.abc() = println("ABC")

String.abc()     直接调用而不通过对象
----
输出
ABC

val String.str1: String     扩展属性只能为 val),同样也有静态扩展属性
    get() = "Hello"

println("".str1)
----
输出
Hello

-------------------------------------------------------
中缀函数条件
1. 为成员函数或扩展函数
2. 函数签名带有 infix 关键字
3. 只接收 1 个参数

infix fun Int.abc(x: Int): Int {
    println("OK!")
    return this + x
}

println(1.abc(2).abc(3))     点号标记法
等同于
println(1 abc 2 abc 3)     中缀标记法
----
输出
OK!
OK!
6

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

Kotlin 中对属性的访问自动转为编译器自动生成的默认 get/set我们可对其进行自定义
----
class A {
    var s: String = "Hi"
        get() {     get 可见性与此属性可见性一致
            println("Get")
            return field
        }
        set(value) {     set 可见性可设置为 private另外 val 没有 set 函数和后备 field
            if (value.startsWith("H")) {
                println("Set true")
                field = value     field当前属性 sthis当前类 A
            } else {
                println("Set false")
            }
        }
}

val a = A()
a.s = "World"
println(a.s)
a.s = "Hello"
println(a.s)
----
输出
Set false
Get
Hi
Set true
Get
Hello

-------------------------------------------------------
委托属性get/set 的工厂函数

class A {
    val s1: String by lazy {     延迟属性只会在第一次访问 get 的时候执行该代码块并赋值延迟加载
        println("123")                     计算时默认为线程同步 synchronized),若不需要可关闭by lazy(LazyThreadSafetyMode.NONE) {}
        "AAA"
    }
    var s2: String by Delegates.observable("XXX") { prop, old, new ->     可观察属性属性改变之后回调afterChange
        println("$old -> $new")               初始值
    }
    var s3: String by Delegates.vetoable("XXX") { prop, old, new ->     可观察属性属性改变之前回调beforeChange
        println("$old -> $new")             初始值
        return@vetoable true     true 接受false 丢弃
    }
}

val a = A()
println(a.s1)
a.s2 = "BBB"
println(a.s2)
a.s3 = "CCC"
println(a.s3)
----
输出
123
AAA
XXX -> BBB
BBB
XXX -> CCC
CCC

委托属性所有属性存储至 Map 中
----
class User(val map: Map<String, Any?>) {     若属性包含 var 则需换成 MutableMap
    val name: String by map     属性名作为 Key
    val age: Int by map
}

val user = User(mapOf("name" to "ABC", "age" to 25))     Key-ValueKotlin 中的 Map 存储的是 Pair
println("${user.name} ${user.age}")
----
输出
ABC 25

-------------------------------------------------------

属性延迟加载延迟初始化
----
class A {
    val a: String by lazy {     val 使用委托属性 by lazy {}只会在第一次访问 get 的时候执行该代码块并赋值
        println("123")
        "AAA"
    }
    lateinit var b: String      var 使用关键字 lateinit可稍后手动初始化若访问 get 时未初始化则抛出 UninitializedPropertyAccessException 异常
}

val a = A()
println(a.a)
a.b = "BBB"
println(a.b)
----
输出
123
AAA
BBB

-------------------------------------------------------
编译期常数值属性值在编译期间就能够确定需满足以下条件
1. 为顶级属性或者是 object 的成员
2. 为 String 或者是基本类型
3.val 且没有自定义的 get 函数

const val i = 5
class A {
    var name = ""
    var age = 20
}
可简化为
class A constructor(var name: String = "", var age: Int = 20) {     主构造函数
}
可简化为
class A(var name: String = "", var age: Int = 20)     主构造函数无注解和修饰符可省略 constructor无类体可省略 {}

-------------------------------------------------------

data class A(var name: String, var age: Int) {     Kotlin 中的类可以有一个主构造函数和多个次构造函数
    init {
        println("主构造函数 or 初始化块")
    }

    constructor(name: String) : this(name, 0) {     声明次构造函数
        println("次构造函数1")
    }

    constructor(age: Int) : this("无名氏", age) {
        println("次构造函数2")
    }
}

println(A("张三", 20))
println(A("张三"))
println(A(20))
//println(A())     报错,没有无参构造函数
----
输出
主构造函数 or 初始化块
A(name=张三, age=20)
-
主构造函数 or 初始化块
次构造函数1
A(name=张三, age=0)
-
主构造函数 or 初始化块
次构造函数2
A(name=无名氏, age=20)

-------------------------------------------------------
如果主构造函数的所有参数都有默认值则默认会生成一个无参次构造函数
如果没有声明任何主或次构造函数则默认会生成一个无参主构造函数

data class A private constructor(var name: String, var des: String) {     指定主构造函数为 private
    constructor(name: String) : this(name, "欢迎:$name")     默认 public
}

println(A("张三"))
//println(A("张三", "ABC"))     报错,主构造函数为 private
----
输出
A(name=张三, des=欢迎张三)

-------------------------------------------------------

import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.BorderPane
import javafx.stage.Stage

fun main(args: Array<String>) {     JavaFX
    Application.launch(A::class.java, *args)     从 KClass 对象获得 Class 对象
}

class A : Application() {     继承 Application 抽象类显式调用构造函数
    override fun start(primaryStage: Stage) {     实现抽象函数
        primaryStage.title = "ABC"
        primaryStage.width = 400.toDouble()
        primaryStage.height = 300.toDouble()
        primaryStage.scene = Scene(BorderPane())
        primaryStage.show()
    }
}
interface A {     接口跟 Java 一样单继承多实现
    val i: Int     抽象属性
    val j: Int     属性已提供访问器实现若属性修饰为 var还需提供 set() 实现
        get() = 2

    fun a()     抽象函数
    fun b() {}     函数已提供函数实现
}

class B : A {     通过类实现接口
    override val i: Int
        get() = 1
    override fun a() {}
}

val a = object : A {     通过对象表达式实现接口匿名内部类
    override val i: Int
        get() = 1
    override fun a() {}
}

-------------------------------------------------------

对象表达式匿名内部类):
val o = object {
    val x = 1
    val y = 2
    val z = 3
    operator fun component1() = x     解构函数
    operator fun component2() = y     解构函数
    operator fun component3() = z     解构函数
}
等同于
val o = object : Any() {     Kotlin 中 Any 是所有类的父类
    val x = 1
    val y = 2
    val z = 3
    operator fun component1() = x
    operator fun component2() = y
    operator fun component3() = z
}

val (x, y, z) = o     解构声明
println(x + y + z)     6
println(o.x + o.y + o.z)     6

-------------------------------------------------------

对象声明单例模式):
object MyObject {     单例对象Singleton
    val AUTHOR = "XhstormR"     属性为 static

    fun hello(): String {     函数不为 static可加上 "@JvmStatic" 注解成为 static 函数针对属性同样还有 "@JvmField"都仅对 Java 互操作有影响
        return "Hello $AUTHOR!"
    }
}

println(MyObject.AUTHOR)
println(MyObject.hello())
----
输出
XhstormR
Hello XhstormR!

-------------------------------------------------------

open class A     A 类

interface B     B 接口

class C : A(), B     C 继承 A 并实现 B类默认生成无参主构造函数接口无构造函数且默认开放
operator操作符重载
----
class A(var i: Int) {
    operator fun inc(): A {     a++
        i++
        return this
    }

    operator fun dec(): A {     a--
        i--
        return this
    }

    operator fun invoke(): Int {     a()
        return i
    }

    operator fun get(index: Int): Int {     a[0]
        return i
    }

    operator fun set(index: Int, int: Int) {     a[0] = 123
        i = int
    }

    operator fun compareTo(o: A): Int {     >,<,>=,<=
        return i.compareTo(o.i)
    }

    override operator fun equals(other: Any?): Boolean {     ==,!=IDE 生成
        if (this === other) return true
        if (other?.javaClass != javaClass) return false
        other as A
        if (i != other.i) return false
        return true
    }

    override fun hashCode(): Int {     IDE 生成
        return i
    }

    override fun toString(): String {     IDE 生成
        return "A(i=$i)"
    }
}
Java
class Test1 {
    static {
        System.out.println("1父类静态初始化块");
    }

    {
        System.out.println("2父类初始化块");
    }

    Test1() {
        System.out.println("3父类构造方法");
    }
}
----
class Test2 extends Test1 {
    static {
        System.out.println("1子类静态初始化块");
    }

    {
        System.out.println("2子类初始化块");
    }

    Test2() {
        System.out.println("3子类构造方法");
    }
}
----
class Initial {
    public static void main(String[] args) {
        Test1 a = new Test2();
    }
}
----
输出
1父类静态初始化块
1子类静态初始化块
2父类初始化块
3父类构造方法
2子类初始化块
3子类构造方法

-------------------------------------------------------

Kotlin
open class Test1 {     Kotlin 跟 Java 相反类和方法都默认为 final最终),需用 open开放指明可以继承
    companion object {     伴生对象静态内部类 Companion)(static 初始化块方法属性
        init {
            println("1父类静态初始化块")
        }
    }

    init {
        println("2父类初始化块")
        println("3父类构造函数(主)")
    }
}
----
class Test2 : Test1() {     需显式调用父类的构造方法
    companion object {     伴生对象静态内部类 Companion)(static 初始化块方法属性
        init {
            println("1子类静态初始化块")
        }
    }

    init {
        println("2子类初始化块")
        println("3子类构造函数(主)")
    }
}
----
fun main(args: Array<String>) {
    val a: Test1 = Test2()     多态
    val companion = Test2.Companion     获得类中的伴生对象
}
----
输出
1父类静态初始化块
1子类静态初始化块
2父类初始化块
3父类构造函数(主)
2子类初始化块
3子类构造函数(主)

-------------------------------------------------------

class A {
    companion object {     伴生对象静态内部类 Companion)(static 初始化块方法属性
        var i = 0
        init {
            println("静态初始化块")
        }
    }

    init {
        println("${++i} 初始化块 构造函数(主)")
    }
}

A()
A()
A()
A()
----
输出
静态初始化块
1 初始化块 构造函数(主)
2 初始化块 构造函数(主)
3 初始化块 构造函数(主)
4 初始化块 构造函数(主)

-------------------------------------------------------

class A {
    companion object {     伴生对象静态内部类 Companion)(static 初始化块方法属性
        val list = arrayListOf<A>()
    }

    init {
        list.add(this)
    }
}

A()
A()
A()
println(A.list)
----
输出
[A@2f0e140b, A@7440e464, A@49476842]

-------------------------------------------------------
默认内部类静态化可在一定程度上降低发生内存泄露的概率
很多时候内部类仅用来存储数据并不需要访问外部类的成员

class Outer {
    private val bar = 1
    class Nested {     Java 中的静态内部类相当于独立出来的类不会持有其外部类的强引用
        fun foo() = 2
    }
}

Outer.Nested().foo()     不需要实例化外部类

----

class Outer {
    private val bar = 1
    inner class Nested {     Java 中的内部类默认持有其外部类的强引用
        fun foo() = bar     可以访问外部类的成员
    }
}

Outer().Nested().foo()     需要实例化外部类
val array = arrayOfNulls<Int>(5)     创建容量为 5null 填充的空数组
for (i in array.indices) {
    println(array[i])
}
----
输出
null
null
null
null
null

-------------------------------------------------------

val s1 = "ABC"
val s2 = StringBuilder("ABC").toString()
println(s1 == s2)      比较实际内容operator 重载调用 equals()),对应 !=
println(s1 === s2)     比较内存地址Java 中的 `==`),对应 !==
----
输出
true
false

-------------------------------------------------------

Kotlin
val a: Char = 'A'     在 Java 中为基本数据类型 char
val b: Char? = 'B'     在 Java 中为引用数据类型 Character
println(a)
println(b)

Convert to Java
char a = 65;
Character b = Character.valueOf('B');
System.out.println(a);
System.out.println(b);

----

Kotlin
val arrayOf = arrayOf(1, 2, 3)
val intArrayOf = intArrayOf(4, 5, 6)     避免装箱提高性能

Convert to Java
Object[] elements$iv = new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)};
Integer[] arrayOf = (Integer[])((Object[])elements$iv);
int[] var10000 = new int[]{4, 5, 6};

-------------------------------------------------------

FileOutputStream("""D:\123.txt""", true).bufferedWriter().use { it.write("${LocalDateTime.now()}\n") }     写
FileInputStream("""D:\123.txt""").bufferedReader().useLines { it.forEach(::println) }     读

-------------------------------------------------------

println(String().javaClass)     从实例对象获得 Class 对象
println(String::class.java)     从 KClass 对象获得 Class 对象
----
输出
class java.lang.String     完全类名限定符
class java.lang.String

Script

D:\Download\kotlinc\bin>kotlinc -script DeleteFile.kts

JavaScript

D:\Download\kotlinc\bin>kotlinc-js -output 123.js A.kt
D:\Download\kotlinc\lib\kotlin-stdlib-js.jar\kotlin.js
@JsName("main")
fun main(args: Array<String>) {
    js("""document.write(message+"<br/>")""")
    alert(message)
}

val message = "Hello JavaScript."

external fun alert(message: Any?)//暴露外部 API
<html>
<head>
    <meta charset="UTF-8">
    <title>123</title>
</head>
<body>
    <script type="text/javascript" src="kotlin.js"></script>
    <script type="text/javascript" src="123.js"></script>
</body>
</html>

Reference