Android开发经验谈Android开发Android开发

Kotlin语法糖--基础

2017-08-17  本文已影响110人  皮球二二

不管你学习什么语言,开篇都是介绍基本类型,然后就是诸如控制流这种入门语法,随后就是对象、函数的使用,最后就是此语言的高级语法了。所以我们也按照这个流程,今天先介绍些简单的知识
本篇文章涉及到的代码已经提交到Github

其实Kotlin中所有东西都是对象,这跟Java有点区别

Kotlin对数字的处理在某种程度上接近Java,但是并不完全相同,比如Java可以将int隐式转换为long,这点Kotlin做不到。
Kotlin提供如下几种类型来表示数字

Type Bit width
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

Kotlin支持二进制、十进制、十六进制,不支持八进制。这里还有几点要注意下:
(1) Long类型要在最后加“L”进行标记,比如100L
(2) 有浮点数默认都为Double,如果你想用Float来表示,那么就要在最后加“F”进行标记,例如100f

这个一般体现在可读性上,比如你说说看100000是多少?在Java中你要从个十百千万的一个个点才知道,但是Kotlin就不同了,看代码

val a: Int=10000
val b: Int=10_000
println(a== b)  // 返回true

刚说了Kotlin中所有东西都是对象,而Java则是将数字存储为JVM的原生类型。所以Kotlin装箱之后,同一性不会被保留,但是保留了相等性。来看看代码吧

val boxA: Int? = a
var anotherBoxA: Int? = a
println(boxA == anotherBoxA)
println(boxA === anotherBoxA)
运行结果

Kotlin里较小类型数不是较大类型数的子类型,所以不能直接隐式转换,并且代码也编译不过去

val a: Int=10000
val c: Long = a  // 无法编译通过

我们可以通过显式的来进行转换

val c: Long = a.toLong()

每个数字类型支持如下的转换:
(1) toByte()
(2) toShort()
(3) toInt()
(4) toLong()
(5) toFloat()
(6) toDouble()
(7) toChar()

字符要用Char类型表示,不能直接当数字使用。字符字面值用单引号括起来,比如'a'。特殊字符可以用反斜杠转义,支持如下几个转义序列\t、\b、\n、\r、\'、 \"、\\和$,其他编码类型要使用Unicode转义序列语法,比如'\uFF00'

两个值true和false

数组在Kotlin中使用Array类来表示
我们一般使用arrayOf来创建一个数组并将元素传递给它

var array: Array<String> = arrayOf("1", "2", "3")

或者通过arrayOfNulls创建一个指定数量并且元素都为空的数组

var array1 = arrayOfNulls<String>(5)

甚至我们可以通过Array的构造方法创建一个基于索引来确定每个元素值的数组

var array2 = Array(5) {
    "$it+Demo"
}

此处涉及到高阶函数部分,我们在后面会详细说明
数组可以通过[]运算符来调用成员函数get与set

var array: Array<String> = arrayOf("1", "2", "3")
array[0]
println(array[0])
array[1]="4"
println(array[1])

还有ByteArray、ShortArray、IntArray,这些跟Array并没有继承关系,但是它们都有同样的方法属性集

Kotlin中的字符串分为转义字符串以及原生字符串。
转义字符串跟Java的差不多,来看看

val text1="Hello \n"

原生字符串使用三个引号(""")分解符括起来,内部没有转义并且可以包含换行和任何其他字符

var text= """
    |ABC""
    |DEF
    |GHI
    """
println(text.trimMargin())
运行结果

默认是使用"|"作为边界前缀,你也可以选择其他字符作为参数传入

字符串可以包含模板表达式,即一些小段代码,并求值把结果合并到字符串中。模板表达式以美元符号$开头

var text="World"
val text12="Hello $text"
运行结果

除此之外,他还可以将表达式通过花括号括起来进行结果显示

println("1+2=${1+2}")
运行结果

最后一点,原生字符串中如果想实现转义功能,也可以通过字符串模板去实现

var text= """
    |ABC""
    |1+2=${'\n'}
    |DEF
    |GHI
    """
println(text.trimMargin())
运行结果

Kotlin中这部分跟Java还是差不多的
我现在同时定义2个类


目录结构

ClassA与ClassB基本上都是相同的,他们都有一个相同的类名字,叫APP


名字相同的类
好了我们现在要同时使用这2个类了
val appa: APP = APP()
val appb: APP = APP()

这样肯定不行的,这个谁不知道啊
要是在Java里面,肯定有一个类的变量类型是全路径显示的,就像这样

APP app=new APP();
com.renyu.kotlin.chapter2.b.APP app1=new com.renyu.kotlin.chapter2.b.APP();

这个实在是太长了是不是。Kotlin就有一个舒服的解决办法,用as关键字来重命名相同命名的冲突项

import com.renyu.kotlin.chapter2.b.APP as BAPP
import com.renyu.kotlin.chapter2.a.APP

这样呢,b包中的APP类就可以通过BAPP来声明了

val appa: APP = APP()
println(appa.value)
val appb: BAPP = BAPP()
println(appb.value)

这个在之前的文章中已经提及了很多,这里也是说重点。除了可以像Java一样作为语句来使用之外,如果你将其作为表达式来使用,必须要有else分支

var a1=10
var b2=20
var maxValue: Int = if (a1>b2) {
    println(a1)
    a1
} else {
    println(b2)
    b2
}
println(maxValue)

最后的表达式就是该语句的值

when取代了switch语句,但是它并不仅仅是替代作用,在使用上when表达式还进行了扩展升级。常用的形式有三种:常量结构、in结构、表达式结构。
when语句与switch语句的区别是,如果符合判断中的任意一条表达式,则在执行表达式对应的语句体之后,直接跳出整个when逻辑,我们不需要手动的break。
如果when语句作为一个表达式来使用,必须要有else分支,除非编译器检测出来你把所有可能发生的情况都考虑到了
先看下典型使用

fun getValue(value: Int) : String {
    return when(value) {
        1 -> "a"
        2 -> "b"
        else -> "other"
    }
}

如果我们希望一个逻辑值value能够对应多个常量值,则我们就必须使用in结构。其操作,与常量结构的when语句类似,即将满足一个条件的多个常量值使用 “,” 隔开如果想合并多个分支,那么用逗号分隔即可

fun getValue(value: Int) : String {
    return when(value) {
        1,3 -> "a"
        2 -> "b"
        else -> "other"
    }
}

同样可以使用任意表达式作为分支条件

fun getValue(value: Int) : String {
    return when(value) {
        1,3 -> "a"
        2 -> "b"
        "5".toInt() -> "e"
        else -> "other"
    }
}

当然,我们也可以将多个表达式对应一个判断同时使用,只需要在两个表达式之间增加“,”符号

最后,我们可以用when来取代if-else if链,我们来改写一下上文的if表达式的例子

var maxValue1: Int = when {
    (a1>b2) -> {
        a1
    } else -> {
        b2
    }
}
println(maxValue1)

不多说了

不多说了

跟Java一样,也是break、continue、return,对比一下Java的写法,应该就能清楚明白了

String[] arrays={"1", "2", "3", "4", "5"};
outer:
for (String array : arrays) {
    System.out.println("1. "+array);
    for (int i=0;i<3;i++) {
        System.out.println("1. "+i);
        if (i==2) {
            break outer;
        }
    }
}
var array3: Array<String> = arrayOf("1", "2", "3", "4", "5")
loop@ for (s in array3) {
    println("1. $s")
    for (i in  0..3) {
        println("2. $i")
        if (i==2) {
            break@loop
        }
    }
}

这里我们可以通过标签来控制返回和跳转流程,标签的格式为标识符后跟@符号

来看一下这几行代码

fun foo() {
    var array: Array<String> = arrayOf("1", "2", "3", "4", "5")
    array.forEach {
        if (it == "2") {
            return
        }
        println("$it")
    }
    println("结束")
}

一旦执行到了这个return,那么我们就将从foo中返回了。我现在想仅从forEach中跳出当前循环,那就必须要给他加标签来限制return了

fun foo() {
    var array: Array<String> = arrayOf("1", "2", "3", "4", "5")
    array.forEach a@{
        if (it == "2") {
            return@a
        }
        println("$it")
    }
    println("结束")
}
return@标签跳出当前Lambda表达式

通常情况下隐式标签更为方便,该标签与lambda的函数同名,即

fun foo() {
    var array: Array<String> = arrayOf("1", "2", "3", "4", "5")
    array.forEach {
        if (it == "2") {
            return@forEach
        }
        println("$it")
    }
    println("结束")
}

入门语法就讲到这里了,下回我们来说说类和对象

上一篇下一篇

猜你喜欢

热点阅读