kotlin代码教程

来源:互联网 发布:小满软件怎么样 编辑:程序博客网 时间:2024/05/16 03:36
// 单行注释用双斜杠 // 开始
/*
这是多行注释.
*/
// 关键词 "package" 的作用跟Java中一样.
package com.learnxinyminutes.kotlin
/*
Kotlin 程序的入口是名为"main"的函数。
命令行参数通过这个方法的数组参数传递。
*/
fun main(args: Array<String>) {
    /*
    声明变量可以用"var" 或者 "val"。
    用"val"声明的参数不能重新赋值,但用"var"声明的可以。
    */
    val fooVal = 10 // 不能再赋别的值给fooVal
    var fooVar = 10
    fooVar = 20 // fooVar可以重新赋值
    /*
    大部分情况下,Kotlin 可以判断变量的类型,所以不用每次都显式声明。
    我们也可以像下面这样显式声明一个变量的类型:
    */
    val foo : Int = 7
    /*
    字符串可以用与Java类似的方式表示。
    用反斜杠转义。
    */
    val fooString = "My String Is Here!"
    val barString = "Printing on a new line?\nNo Problem!"
    val bazString = "Do you want to add a tab?\tNo Problem!"
    println(fooString)
    println(barString)
    println(bazString)
    /*
    原始字符串(raw string)由三重引号(“”“)分隔。
    原始字符串可以包含换行符和任何其他字符。
    */
    val fooRawString = """
fun helloWorld(val name : String) {
   println("Hello, world!")
}
"""
    println(fooRawString)
    /*
    字符串可以包含模板表达式。
    模板表达式以美元符号($)开始。
    */
    val fooTemplateString = "$fooString has ${fooString.length} characters"
    println(fooTemplateString)
    /*
    要使变量保持为null,必须将其显式指定为可空。
    在变量类型后面加上 ? 符号,即声明为可空。
    用 ?. 运算符来访问一个可空的变量。
    用 ?: 运算符来指定当该变量为空时的替代值
    */
    var fooNullable: String? = "abc"
    println(fooNullable?.length) // => 3
    println(fooNullable?.length ?: -1) // => 3
    fooNullable = null
    println(fooNullable?.length) // => null
    println(fooNullable?.length ?: -1) // => -1
    /*
    用“fun”关键字声明函数。
    函数参数在函数名后面的括号中指定。
    函数参数可以选择具有默认值。
    函数返回类型(如果需要的话)在参数之后指定。
    */
    fun hello(name: String = "world"): String {
        return "Hello, $name!"
    }
    println(hello("foo")) // => Hello, foo!
    println(hello(name = "bar")) // => Hello, bar!
    println(hello()) // => Hello, world!
    /*
    用“vararg”关键字标记函数参数,
    则允许将可变数量的参数传递给函数。
    */
    fun varargExample(vararg names: Int) {
        println("Argument has ${names.size} elements")
    }
    varargExample() // => Argument has 0 elements
    varargExample(1) // => Argument has 1 elements
    varargExample(1, 2, 3) // => Argument has 3 elements
    /*
    当函数由单个表达式组成时,可以省略大括号,
    直接在 = 符号后写函数体。
    */
    fun odd(x: Int): Boolean = x % 2 == 1
    println(odd(6)) // => false
    println(odd(7)) // => true
    // 如果可以推断出返回类型,那么不需要显式声明它。
    fun even(x: Int) = x % 2 == 0
    println(even(6)) // => true
    println(even(7)) // => false
    // 一个函数可以接受另一个函数作为参数,也可以返回一个函数。
    fun not(f: (Int) -> Boolean): (Int) -> Boolean {
        return {n -> !f.invoke(n)}
    }
    // 用 :: 操作符把一个命名函数用作参数。
    val notOdd = not(::odd)
    val notEven = not(::even)
    // Lambda 表达式可以当作参数。
    val notZero = not {n -> n == 0}
    /*
    如果lambda只有一个参数,
    那么它的声明可以(与 -> 一起)省略。
    单个参数的名称将是“it”。
    */
    val notPositive = not {it > 0}
    for (i in 0..4) {
        println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")
    }
    // "class" 关键字用于类声明。
    class ExampleClass(val x: Int) {
        fun memberFunction(y: Int): Int {
            return x + y
        }
        infix fun infixMemberFunction(y: Int): Int {
            return x * y
        }
    }
    /*
    调用构造函数来创建一个实例。
    注意,Kotlin没有 “new” 这个关键字。
    */
    val fooExampleClass = ExampleClass(7)
    // 可以使用 . 符号来调用成员函数。
    println(fooExampleClass.memberFunction(4)) // => 11
    /*
    如果一个函数用 “infix” 关键字标记,称为中缀标记。
    */
    println(fooExampleClass infixMemberFunction 4) // => 28
    /*
    数据类是创建一种只用于保存数据的类的简洁方法。
    “hashCode”、“equals”和“toString”方法都是自动生成的。
    */
    data class DataClassExample (val x: Int, val y: Int, val z: Int)
    val fooData = DataClassExample(1, 2, 4)
    println(fooData) // => DataClassExample(x=1, y=2, z=4)
    // 数据类有一个“copy”方法。
    val fooCopy = fooData.copy(y = 100)
    println(fooCopy) // => DataClassExample(x=1, y=100, z=4)
    // 对象可以被解构成多个变量。
    val (a, b, c) = fooCopy
    println("$a $b $c") // => 1 100 4
    // 解构声明用于for循环中
    for ((a, b, c) in listOf(fooData)) {
        println("$a $b $c") // => 1 100 4
    }
    val mapData = mapOf("a" to 1, "b" to 2)
    // Map.Entry 也被解构了
    for ((key, value) in mapData) {
        println("$key -> $value")
    }
    // "with" 方法与JavaScript中的 "with" 声明类似.
    data class MutableDataClassExample (var x: Int, var y: Int, var z: Int)
    val fooMutableData = MutableDataClassExample(7, 4, 9)
    with (fooMutableData) {
        x -= 2
        y += 2
        z--
    }
    println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8)
    /*
    可以用 "listOf" 方法创建一个list。
    这个list是不可变的 —— 不能增加或删除元素。
    */
    val fooList = listOf("a", "b", "c")
    println(fooList.size) // => 3
    println(fooList.first()) // => a
    println(fooList.last()) // => c
    // 可以通过序号获取list中的元素。
    println(fooList[1]) // => b
    // 用 "mutableListOf" 方法创建可变列表.
    val fooMutableList = mutableListOf("a", "b", "c")
    fooMutableList.add("d")
    println(fooMutableList.last()) // => d
    println(fooMutableList.size) // => 4
    // 用 "setOf" 方法创建集合.
    val fooSet = setOf("a", "b", "c")
    println(fooSet.contains("a")) // => true
    println(fooSet.contains("z")) // => false
    // 用 "mapOf" 方法创建 map.
    val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9)
    // 在map中,通过 kep 来获取 value.
    println(fooMap["a"]) // => 8
    //用 "generateSequence" 方法创建一个序列.
    val fooSequence = generateSequence(1, { it + 1 })
    val x = fooSequence.take(10).toList()
    println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    // 用序列生成斐波那契数的例子。
    fun fibonacciSequence(): Sequence<Long> {
        var a = 0L
        var b = 1L
        fun next(): Long {
            val result = a + b
            a = b
            b = result
            return a
        }
        return generateSequence(::next)
    }
    val y = fibonacciSequence().take(10).toList()
    println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    // Kotlin 提供了更高级的功能来处理集合。
    val z = (1..9).map {it * 30}
                  .filter {it < 20}
                  .groupBy {it % 2 == 0}
                  .mapKeys {if (it.key) "even" else "odd"}
    println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]}
    // "for" 循环可以用于任何有迭代器的东西.
    for (c in "hello") {
        println(c)
    }
    // "while" 循环与其它语言中用法一样.
    var ctr = 0
    while (ctr < 5) {
        println(ctr)
        ctr++
    }
    do {
        println(ctr)
        ctr++
    } while (ctr < 10)
    /*
    “if” 表达式可以直接返回值。
    因此,Kotlin 不需要三元运算符 ?:
    */
    val num = 5
    val message = if (num % 2 == 0) "even" else "odd"
    println("$num is $message") // => 5 is odd
    // "when" 可以代替 "if-else if".
    val i = 10
    when {
        i < 7 -> println("first block")
        fooString.startsWith("hello") -> println("second block")
        else -> println("else block")
    }
    // "when" 可以带参数.
    when (i) {
        0, 21 -> println("0 or 21")
        in 1..20 -> println("in the range 1 to 20")
        else -> println("none of the above")
    }
    // "when" 可以当作函数,并返回值.
    var result = when (i) {
        0, 21 -> "0 or 21"
        in 1..20 -> "in the range 1 to 20"
        else -> "none of the above"
    }
    println(result)
    /*
    可以用“is”运算符检查对象是否是特定类型。
    如果对象通过了类型检查,就可以把它当作这个类型来用,无需显示转换。
    */
    fun smartCastExample(x: Any) : Boolean {
        if (x is Boolean) {
            // x is automatically cast to Boolean
            return x
        } else if (x is Int) {
            // x is automatically cast to Int
            return x > 0
        } else if (x is String) {
            // x is automatically cast to String
            return x.isNotEmpty()
        } else {
            return false
        }
    }
    println(smartCastExample("Hello, world!")) // => true
    println(smartCastExample("")) // => false
    println(smartCastExample(5)) // => true
    println(smartCastExample(0)) // => false
    println(smartCastExample(true)) // => true
    // Smartcast 也可以用于 when。
    fun smartCastWhenExample(x: Any) = when (x) {
        is Boolean -> x
        is Int -> x > 0
        is String -> x.isNotEmpty()
        else -> false
    }
    /*
    扩展是向类里添加新功能的一种方法。
    这与C#的扩展方法类似。
    */
    fun String.remove(c: Char): String {
        return this.filter {it != c}
    }
    println("Hello, world!".remove('l')) // => Heo, word!
    println(EnumExample.A) // => A
    println(ObjectExample.hello()) // => hello
}
// 枚举类与Java的枚举类型相似.
enum class EnumExample {
    A, B, C
}
/*
"object" 关键字可用于创建单例对象。
我们不能实例化它,但我们可以通过它的名称来引用它的唯一实例。
这与Scala的单例对象类似。
*/
object ObjectExample {
    fun hello(): String {
        return "hello"
    }
}
fun useObject() {
    ObjectExample.hello()
    val someRef: Any = ObjectExample // 可以直接使用对象名称
}