方法定义
强类型的语言所以参数和返回值必须定义类型1
2
3fun sum(a: Int, b: Int): Int {
return a + b
}
像上例中,如果函数体只有一个表达式,而且能推断出返回类型时,可以写成这样:1
fun sum(a: Int, b: Int) = a + b
如果无返回类型,那么返回类型可以写1
2
3
4
5#### 声明变量
只读变量,相当于Java中用final修饰的,使用val声明
``` Kotlin
val a: Int = 1
val b = 2 // 这里省略类型是因为此时类型是可以推断出来的
可变变量,使用关键字var声明1
2var c = 5 // 类型同样可推断
c += 5
字符串模板
Kotlin中有类似JavaScript的字符串模板1
2
3
4var c = 5
val s1 = "a is $c" // now, s1 = "a is 5"
val s2 = "abc"
val s3 = "$s2.length is ${s2.length}" // now, s3 = "abc.length is 3"
空安全
空安全从来都是一件让人头疼的事情,在Java里,你总是会由于没有做空安全保护说不定哪里就会报类似NullPointerException。
- 可空变量的声明
首先,下面这种做法是不行的1
2
3// eg1
var a: String = "abc"
a = null // compilation error
因为限定了a的类型是String,那么它就不可以持有null对象
怎么纠正?1
2
3// eg2
var b: String? = "abc"
b = null // OK
- 可空变量的访问
首先如果我们访问eg1中的a,比如l 1
2
3
4这是没问题的,为什么呢,因为a被限定死是String类型,而且也只能被赋予String类型的值,那么,无论如何它不为空,一定有length成员
那么如果我们访问eg2中的b呢
``` Kotlin
val l = b.length // error: variable 'b' can be null
这时候,我们就需要做空保护了,传统地,我们可以像Java中做空保护一样这样写1
2
3
4
5if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
或者用Kotlin的判断语句表达式1
val l = if (b != null) b.length else -1
还有一种最便利的安全操作符?.
比如1
2
3这种最方便于链式调用,比如
```Kotlin
bob?.department?.name?.head
过程中有任意一项为空,表达式都会返回null
is(反义是!is)与自动类型转换
is操作符是用来判断一个对象是否是一个类型的实例1
2
3
4
5
6
7
8fun getStringLength(obj: Any): Int? {
if (obj is String) {
// `obj` is automatically cast to `String` in this branch
return obj.length
}
// `obj` is still of type `Any` outside of the type-checked branch
return null
}
从上面的例子可以看出,经过is进行类型检查以后,就没有必要进行类型转换了,对象会自动转换成被检查的类型。
when——一个更优秀的switch替代品
when结构里的判断项相当的灵活,可以是一个常量,也可以是表达式(函数,类型检查,范围等)。举例说明:1
2
3
4
5when (x) {
0, 1 -> print("x == 0 or x == 1")
2 -> print("x ==2")
else -> print("otherwise")
}
1 | when (x) { |
1 | fun hasPrefix(x: Any) = when(x) { |
when还可以用作多重if/else选择的替代:1
2
3
4
5when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
as强制类型转换
首先声明强制类型转换是非安全的,可能抛出异常。
e.g.:1
val x: String = y as String
注意如果y可以为null,而null是不可以转换成String的,就会抛出异常。
怎么改正呢?1
val x: String? = y as String?
前后都可以为空对象。
in 范围判断
先介绍一下在kotlin中可以这样表示范围如1
2
3
4
5
6
7
8
9
10
11
12
13配合in操作符就可以理解其表示的含义
e.g..:
```Kotlin
if (i in 1..10) { // equivalent of 1 <= i && i <= 10
println(i)
}
for (i in 1..4) print(i) // prints "1234"
for (i in 4..1) print(i) // prints nothing
for (i in 4 downTo 1) print(i) // prints "4321"
for (i in 1..4 step 2) print(i) // prints "13"
for (i in 1 until 10) { // i in [1, 10), 10 is excluded 不包括10,注意⚠️
println(i)
}
Collections集合与循环/判断
迭代器与集合
和其他语言类似:1
2
3for (item in items) {
println(item)
}判断元素与集合的关系
1
2
3
4when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
可见性修饰
Kotlin有四种可见性修饰符:private, protected, internal, public
用法见下面表格:
修饰符 | 顶级(声明在package底下) | 类级(声明在一个类里) |
---|---|---|
private | 当前文件可见 | 只当前类可见 |
protected | (不可直接在包下使用此声明) | 当前类及其子类可见 |
internal | 当前module可见 | 当前module可见 |
public | 随处可见 | 随处可见 |
值得注意的是,如果不做修饰,默认则是public
例子:
顶级
1
2
3
4
5
6// file name: example.kt
package foo
private fun foo() {} // visible inside example.kt
public var bar: Int = 5 // property is visible everywhere
private set // setter is visible only in example.kt
internal val baz = 6 // visible inside the same module类级
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20open class Outer {
private val a = 1
protected open val b = 2
internal val c = 3
val d = 4 // public by default
protected class Nested {
public val e: Int = 5
}
}
class Subclass : Outer() {
// a is not visible
// b, c and d are visible
// Nested and e are visible
override val b = 5 // 'b' is protected
}
class Unrelated(o: Outer) {
// o.a, o.b are not visible
// o.c and o.d are visible (same module)
// Outer.Nested is not visible, and Nested::e is not visible either
}
可继承声明
继承修饰符open(与java的final相对),使用Kotlin声明一个可以被继承的类必须冠以open