Kotlin基本语法

Kotlin语法简洁,主要的几种区别或重点如下:
- 不用分号结尾
- 没有new关键字
- “:”很重要
- 参数名在前,类型在后
- …

包的定义

包的指定需要位于源文件的最顶部。(和Java相同)示例如下:

package com.xingfeng_coder.basic.syntas

/**
 * Created by Xingfeng on 2017-06-12.
 */

函数的定义

  • 下面的函数定义有两个Int形参并且返回值是Int类型,代码如下:
fun sum_1(a: Int, b: Int): Int {
    return a + b
}
  • 下面的函数使用表达式并自动推出返回值,代码如下:
fun sum_2(a: Int, b: Int) = a + b
  • 下面的函数的返回值为没有意义的值,代码如下:
fun printSum_1(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}
  • Unit可以省略,函数定义如下:
fun printSum_2(a: Int, b: Int) {
    println("sum of $a and $b is ${a + b}")
}

变量的定义

只赋值一次(只读)变量

 val a: Int = 1   //声明并赋值
    val b = 2     //声明并赋值,但是类型需要推断
    val c: Int   //先声明
    c = 3   //后赋值
//    b = 1   //尝试修改b的值,报错

从上面可以看出,只读变量类似Java中的final字段,需要使用val关键字进行声明变量。

可变变量

var x = 3
    x += 1
    println(x)

变量的定义使用var关键字,结果输出为4

注释

这个没有好说的

/**
     * 演示变量的定义,包括常量和变量
     */  

//声明并赋值

使用字符串模板

fun main(args: Array<String>) {
    var a=1
    val s1="a is $a"
    a=2
    val s2="${s1.replace("is","was")},but now is $a"
    println(s1)
    println(s2)
}

运行结果如下:

a is 1
a was 1,but now is 2

模板表达式由”$”符开始,并由一个简单的名称组成,也可以是{}括号表示的任意表达式。
比如下面的代码:

val s = "abc"
val str = "$s.length is ${s.length}"

str的值这儿就表示”abc.length is 3”

条件表达式

先看下面一个找出两个数中较大数的函数:

fun maxOf(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}

使用if表达式,可以改写成如下形式:

fun maxOfUsingIfExpress(a: Int, b: Int) = if (a > b) a else b

If表达式

在Kotlin中,if是一个表达式,它返回一个值。因此Kotlin不提供三元运算符(condition?then:else),因此if表达式就可以很好地取代该功能。

// 传统用法
var max = a
if (a < b) max = b

// 使用if-else
var max: Int
if (a > b) {
max = a
} else {
max = b
}


// 使用if表达式
val max = if (a > b) a else b

如果if的分支是语句块,那么最后一个表达式就是该块的返回值:如下:

    val max2 = if (a > b) {
        print(a)
        a
    } else {
        print(b)
        b
    }

使用可能为null的值并且检查null类型

当一个引用指向的值可能为null的时候,那么需要显式地指明该引用可能为null。
下面的函数将会在str转换不了整形时返回null

fun parseInt(str: String): Int? {
    //模拟转换
    return if (str.equals("1")) 1 else null
}

fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

    if (x != null && y != null) {
        println(x * y)
    } else {
        println("either '$arg1' or '$arg2' is not a number")
    }

}

fun main(args: Array<String>) {

    printProduct("1", "2")
    printProduct("1", "1")

}

Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为null或配合?:做空判断处理

类型检查和自动转型

is关键字用来检查一个表达式是否是某一类型的实例。如果一个不可变的局部变量或属性被检查成一个指定类型,那么没有必要显式转换。
下面的函数用于获取String的长度,但是形参可以是任意类型,所以要判断类型。下面一共有三种写法,代码如下:

fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        //obj 在该分支下会自动转换成“String”类型
        return obj.length
    }

    //obj 仍然是外部分支的“Any”类型
    return null

}

fun getStringLength_1(obj: Any): Int? {

    if (obj !is String) return null
    //obj 在该分支下被自动转型为“String”类型
    return obj.length

}

fun getStringLength_2(obj: Any): Int? {

    if (obj is String && obj.length > 0)
        return obj.length

    return null

}

上面三种写法都是等价的。
可以看到is关键字等同于Java的instanceof关键字,并且更简洁了,因为不需要像Java一样强制转换

循环

for循环

首先看个例子,代码如下:

//for循环 demo
    val items = listOf("apple", "banana", "kiwi")  //listOf()的返回值是List类型
    for (item in items) {
        println(item)
    }

    //List的indices参数表示下标的集合
    for (index in items.indices) {
        println("item at $index is ${items[index]}")
    }

其输出如下:

apple
banana
kiwi
item at 0 is apple
item at 1 is banana
item at 2 is kiwi

for循环可以用于提供了迭代器的任何对象。语法如下:

for(itemn in collection) print(item)  

for循环的主体可以是一个语句块。

for(item:Int in ints){
    //...
}

当for循环用于数组时,会被编译成基于索引的循环。如果你想使用索引迭代一个数组或list,可以像下面这么做:

for(i in array.indices){
    print(array[i])
}

注意,这个“通过范围的迭代”被编译为最优实现,而没有创建额外的对象
或者,你可以使用widthIndex函数,如下

    val items = listOf("apple", "banana", "kiwi")  //listOf()的返回值是List类型
 var index = 0
    while (index< items.size) {
        println(items[index])
        index++
    }

while和do..while循环和Java的一样。

while(x>0){
    x--
}

do{
    val y=retrieveData()
}while(y!=null) //y在这儿是可见的

when表达式

Kotlin去除了switch,但是引入了更为强大的when表达式,例子如下:

fun describe(obj: Any): String =

        when (obj) {

            1 -> "One"
            "Hello" -> "Greeting"
            is Long -> "Long"
            !is String -> "Not a string"
            else -> "Unknown"

        }

fun main(args: Array<String>) {
    println(describe(1))
    println(describe(2L))
    println(describe("Hello"))
    println(describe(3.2))
}

其结果如下:

One
Long
Greeting
Not a string

when取代了Java、C++中的switch。它最简单的使用形式如下:

when(x){

    1 -> print("x==1")
    2 -> print("x==2")
    else ->{
        print("x is neither 1 nor 2")
    }

}

when顺序匹配所有分支,直到有分支满足。when既可以用作表达式,也可以用作一个生命。如果用作表达式,那么满足的分支返回的值就是表达式的值。如果用作生命,每个分支的返回值将会被忽略。
如果所有分支都不满足,那么将会走else分支。如果when被用作表达式,那么else分支是强制要求的,除非编译器能够证明所有可能的情况都包含分支条件。
如果很多情况需要以同一种方式处理,那么分支情况可以以逗号进行分割,如下:

fun someCaseSameHandle(obj: Int){

    when(obj){

        0,1 -> println("obj==0 or obj==1")
        else -> println("otherwise")

    }

}

我们可以使用任意表达式作为分支的情况,不仅仅是常量值,如下:

when(x){

    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")

}

我们还可以检查一个值是否in!in在一个范围里或一个集合里

fun rangeWhen(x: Any) {

    val validNumbers = listOf("1", "2", "3")

    when (x) {

        in 1..10 -> println("x is in the range")  //位于一个范围
        in validNumbers -> println("x is valid")  //位于数组中
        !in 10..20 -> println("x is outside the range") //在范围之外
        else -> println("none of the above")
    }


}

fun main(args: Array<String>) {

    rangeWhen(1)
    rangeWhen("1")
    rangeWhen(11)
    rangeWhen(30)

}

运行结果如下:

x is in the range
x is valid
none of the above
x is outside the range

when还可以和is或!is联合使用。需要注意的是is带来的自动转型,所以不再需要做额外的类型检查了。代码如下:

fun hasPrefix(x: Any) = when (x) {

    is String -> x.startsWith("kotlin")
    else -> false

}

when还可以被用来取代if-else链。如果没有参数提供给when,那么分支条件将会默认是布尔表达式,只有在分支为true时,分支才会执行。

fun replaceIfElse(x:Int){

    when{
        x/2==0 -> println("x is even")
        x/2==1 -> println("x is odd")
        else -> print("i don't know")
    }

}

从上面可以看到when表达式的强大之处:可以与in、!in或集合配合使用来检查范围,可以使用逗号来分隔不同情况的相同处理逻辑,可以与is配合使用,还可以取代if-else等等。

使用范围

在when表达式的介绍中已经涉及了in关键字,in关键字用来检查一个数字是否在一个范围里。

val x=10
    val y=9
    if(x in 1..y+1){
        println("fits in range")
    }

还可以使用!in来检查一个数字是否超出了某个范围

 val list= listOf("a","b","c")
    if(-1 !in 0..list.lastIndex){
        println("-1 is out of range")
    }
    if(list.size !in list.indices){
        println("list size is out of valid list indices range too")
    }

可以使用for循环在一个范围上迭代:

for(x in 1..5){
    print(x)
}

除了在一个范围上以步长为1进行迭代,还可以使用step指定步长,如下:

for (x in 1..10 step 2) {
        println(x)
    }

    for (x in 9 downTo 0 step 3) {
        println(x)
    }

Range表达式用来定义任何可比较的类型,但是用在基本数值类型时,编译器会有优化。
上面可以看到in后面如果跟的是a..b,那么范围在[a,b]之间,a、b均包含,那么如果想范围在[a,b)之间,那么除了使用a..b-1这种形式,还可以使用如下形式:

for(x in 1 until 10){
    print(x)
}

当使用until时,范围为[1,10)。

集合

在一个集合上迭代,代码如下:

for (item in items) {
println(item)
}

使用in操作检查一个集合是否包括某个对象:

when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}

使用lambda表达式来过滤和映射集合:

fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }

代码请见Github

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值