数据类
1
|
data class Customer(val name: String, val email: String)
|
Customer提供了以下方法:
- getters,如果成员变量使用var定义那么还默认提供setters
- equals()
- hashCode()
- toString()
- copy()
- component1(), component2() …
这跟Scala的case class
基本上差不多,一般在做数据交互/传输时用
函数默认值
1
|
fun foo(a: Int = 0, b: String = "") { ... }
|
列表过滤
1
|
val positives = list.filter { x -> x > 0 }
|
或者更短一点
1
|
val positives = list.filter { it > 0 }
|
默认使用it来接收单个的参数
字符串插值
对象检查
1
2
3
4
5
|
when (x) {
is Foo -> ...
is Bar -> ...
else -> ...
}
|
非常精简,再也不要写Java那个烦人的instanceof
遍历映射/列表
1
2
3
|
for ((k, v) in map) {
println("$k -> $v")
}
|
k, v分别是map的key和value,是list的index和value
使用范围
1
2
3
4
5
|
for (i in 1..100) { ... } // closed range: includes 100
for (i in 1 until 100) { ... } // half-open range: does not include 100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }
|
只读映射/列表
1
2
|
val list = listOf("a", "b", "c")
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
|
如果是集合是不是还有setOf
,命名的统一性也是Kotlin的一个亮点,如果你使用过php的话,感觉函数总是记不住。
映射访问
1
2
|
println(map["key"])
map["key"] = value
|
懒值(Lazy)
1
2
3
|
val p: String by lazy {
// compute the string
}
|
这段代码在定义的时候是不会执行变量的值的,只有在使用这个变量的时候才会求值
扩展
这是Kotlin一个非常强大的功能,可以对原来已经存在的类添加一系列的新方法,扩展别人的包非常方便
1
2
3
|
fun String.spaceToCamelCase() { ... }
"Convert this to camelcase".spaceToCamelCase()
|
单例
做Java是不是会经常被问单例模式是怎么实现的,Kotlin直接使用object来定义,直白得不要不要的,这和Scala也是一样的
1
2
3
|
object Resource {
val name = "Name"
}
|
null值检查
1
2
3
|
val files = File("Test").listFiles()
println(files?.size)
println(files?.size ?: "empty")
|
相比Java的if (files != null)
优雅太多了。files如果是空值,新手写代码如果不做Null检查,就会碰到最常见的NullException。Kotlin使用问号来检查,并且null值会一值传递到最后。
1
2
|
val data = ...
val email = data["email"] ?: throw IllegalStateException("Email is missing!")
|
Kotlin使用?:
也是非常的简洁,如果data["email"]
有值,直接使用,如果没有就抛出异常。如果想只有在有值的情况下
1
2
3
4
5
|
val data = ...
data?.let {
... // execute this block if not null
}
|
映射空值检查
1
2
3
|
val data = ...
val mapped = data?.let { transformData(it) } ?: defaultValueIfDataIsNull
|
when表达式作为返回值
Kotlin是基于表达式,而不是基于语句的。也就是说任何的语言结构都是有返回值的,这也是和Scala是一样的。
1
2
3
4
5
6
7
8
|
fun transform(color: String): Int {
return when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
}
|
这里when
是一个表达式,表达式是有值的,如果color是Green,那么这个when
的值就是2
try/catch
同样try/catch也是有值的
1
2
3
4
5
6
7
8
9
|
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
// Working with result
}
|
if
if也是表达式,也是有值的
1
2
3
4
5
6
7
8
9
|
fun foo(param: Int) {
val result = if (param == 1) {
"one"
} else if (param == 2) {
"two"
} else {
"three"
}
}
|
如果上面最后那个else没有写的话,编译是通不过的,如果if
作为一个表达式,那么必须覆盖所有的情况。
使用with调用多个方法
这个特性也比较酷,结构跟python的差不多:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
penDown()
for(i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
|
Java 7的try-with-resources语句
在Java 7的写法如下
1
2
3
|
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
|
在Kotlin写法更加直观
1
2
3
4
|
val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
println(reader.readText())
}
|
泛型
1
2
3
4
5
6
|
// public final class Gson {
// ...
// public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
// ...
inline fun <reified T: Any> Gson.fromJson(json): T = this.fromJson(json, T::class.java)
|
可空布尔类型使用
1
2
3
4
5
6
|
val b: Boolean? = ...
if (b == true) {
...
} else {
// `b` is false or null
}
|