Kotlin语法小结(2)-程序结构

Kotlin语法小结(2)-程序结构

二、程序结构

1、Kotlin访问控制修饰符

在Kotlin中拥有public、internal、protected、private修饰符,作用也和Java几乎一样,与Java不同的是,在Kotlin中,类的声明默认是public的。

修饰符 类成员 顶级声明
public(default) 任何地方可见 任何地方可见
internal 在同一module中可见 在同一module中可见
protected 在子类中可见 -
private 在类内部可见 在当前文件中可见
2、控制流: if、 when、 for、 while、 do while
  • if表达式
1
2
3
4
5
6
7
fun testIf() {
val a : Int = 1
val b : Int = 1
var max = if (a > b) a else b
if (a > b)
max = a
}
  • when表达式,替代Java switch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
fun testWhen() {
// 1、简单用法
val x: Int = 1
when (x) {
1 -> println("x == 1")
2 -> println("x == 2")
else -> {
println("x is neither 1 nor 2")
}
}

// 2、如果很多分支需要相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:
when (x) {
0, 1 -> println("x == 0 or x == 1")
else -> println("otherwise")
}

// 3、可以用任意表达式(而不只是常量)作为分支条件
when (x) {
parseInt("10") -> println("s encodes x")
else -> println("s does not encode x")
}

// 4、可以检测一个值在(in)或者不在(!in)某个区间或者集合
val y: Any = "a"
when (y) {
in 1..10 -> println("x is in the range")
!in 10..20 -> println("x is outside the range")
else -> println("none of the above")
}

// 5、检测一个值是(is)或者不是(!is)某个特定类型的值,由于智能转换,你可以访问该类型的方法和属性而需任何额外的检测。
val result = when (y) {
is String -> y.startsWith("prefix")
is Int -> y + 1
else -> false
}
println(result)
}
  • for循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun testFor() {
// 1、遍历某个区间
for (i in 0..4)//为闭区间[0,4]
println(i)

// 2、通过索引遍历一个数组或者一个 list,你可以这么做:
val array = arrayOf(1, 2, 3)
for (i in array.indices)
println(array[i])

// 3、Arrays库函数 withIndex :
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
}
  • while、 do while使用方法不变
3、返回和跳转

Kotlin 有三种结构化跳转表达式:
return。默认从最直接包围它的函数或者匿名函数返回。
break。终止最直接包围它的循环。
continue。继续下一次最直接包围它的循环。

4、lateinit 延迟初始化成员变量

Java 定义的类成员变量如果不初始化,那么基本类型被初始化为其默认值,比如 int 初始化为 0,boolean 初始化为 false,非基本类型的成员则会被初始化为 null。

1
2
3
4
5
6
public class Hello{
private String name;
}
class Hello{
private var name: String? = null
}

使用了可空类型,副作用就是后面每次你想要用 name 的时候,都需要判断其是否为 null。如果不使用可空类型,需要加 lateinit 关键字:

1
2
3
class Hello{
private lateinit var name: String
}

lateinit 是用来告诉编译器,name 这个变量后续会妥善处置的。

对于 final 的成员变量,Java 要求它们必须在构造方法或者构造块当中对他们进行初始化:

1
2
3
public class Hello {
private final String name = "Peter";
}

也就是说,如果我要想定义一个可以延迟到一定实际再使用并初始化的 final 变量,这在 Java 中是做不到的。

Kotlin 有办法,使用 lazy 这个 delegate 即可:

1
2
3
4
5
class Hello{
private val name by lazy (LazyThreadSafetyMode.SYNCHRONIZED){
NameProvider.getName()
}
}

只有使用到 name 这个属性的时候,lazy 后面的 Lambda 才会执行,name 的值才会真正计算出来。

5、异常捕获
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* Created by chenfeiyue on 2018/4/13.
* Description: Exception
* Kotlin中的try关键字就像 if 和 when 一样,引入了一个表达式
*/
@Throws(Exception::class)
internal fun test(string: String) {
string.toInt()
}

fun main(args: Array<String>) {
val result = try {
10
} catch (e: Exception) {
e.printStackTrace()
-1
} finally {
}
print(result)
}

/**
* kotlin不区分受检异常和未受检异常,不必指定函数抛出的异常,可以处理也可以不处理异常。
*/
fun write() {
val file = File("test.txt")
var outputStream: OutputStream? = null
try {
file.createNewFile()
outputStream = FileOutputStream(file)
val b = "Hello World".toByteArray(charset("UTF-8"))
outputStream.write(b)
} finally {
if (outputStream != null) {
outputStream.close()
}
}
}

参考

Kotlin中文站

Kotlin控制流