Kotlin 作为一个实践导向的语言,当然是更加注重实践,它里面有很多习语,也就是经常使用的特定写法,来让开发更加快捷,同时也形成了 Kotlin 的风格。
Kotlin 鼓励大家推荐自己喜欢的习语,一个的语言升级有可能会加入,这正好跟 Java 相反,Java 就感觉太死板了。
闲话少说,我们进入正题
创建 DTO(POJOs/POCOs)
1
| data class Customer(val name: String, val email: String)
|
会提供一个带有以下功能的对象:
- 为所有属性生成 Getter 方法,如果属性是可变的,也会生成 Setter 方法
- equals()
- hashCode()
- toString()
- copy()
- 为所有属性生成 component1(), component2()…
方法参数的默认参数
1
| fun foo(a: Int = 0, b: String = "") { ... }
|
拥有了方法默认参数,就可以只赋值必须的几个参数,而其余使用默认,是不是很爽。
过滤一个列表
1
| val positives = list.filter { x -> x > 0 }
|
或者更简单一点
1
| val positives = list.filter { it > 0 }
|
字符串内插值
还有更强大的
1
| println("Name ${ upperCase(user.Name) }")
|
表达式的结果填入字符串
检查一个实例是某个类的对象
1 2 3 4 5
| when (x) { is Foo -> ... is Bar -> ... else -> ... }
|
遍历一个 map
1 2 3
| for ((k, v) in map) { println("$k -> $v") }
|
k,v 可以取任意名
取值范围
1 2 3 4 5
| for (i in 1..100) { ... } for (i in 1 until 100) { ... } for (x in 2..10 step 2) { ... } for (x in 10 downTo 1) { ... } if (x in 1..10) { ... }
|
只读的列表
1
| val list = listOf("a", "b", "c")
|
只读 Map
1
| val map = mapOf("a" to 1, "b" to 2, "c" to 3)
|
访问一个 Map
1 2
| println(map["key"]) map["key"] = value
|
这个都算,我就没见过 map 不这样操作的
懒加载属性
1 2 3
| val p: String by lazy { }
|
这个才算是棒,在第一次使用的时候初始化属性
扩展函数
1 2 3
| fun String.spaceToCamelCase() { ... }
"Convert this to camelcase".spaceToCamelCase()
|
这也是高能,竟然能对那些司空见惯的对象添加新功能,不知道这是好事还是坏事,凡是自由,都需要限制。
创建单例
1 2 3
| object Resource { val name = "Name" }
|
上一篇文章,已经和 Java 的单例对比了,简洁!!
判断非 null 的快捷方式
1 2 3
| val files = File("Test").listFiles()
println(files?.size)
|
判断 files 如果非 null 则返回 size 的值,否则返回 null
判断非 null 以及 null 情况的处理方式 的快捷方式
1 2 3
| val files = File("Test").listFiles()
println(files?.size ?: "empty")
|
判断 files 如果非 null 则返回 size 的值,否则返回 empty
在判断是 null 时执行一个语句
1 2
| val data = ... val email = data["email"] ?: throw IllegalStateException("Email is missing!")
|
判断输入不是 null 时执行
1 2 3 4 5
| val data = ...
data?.let { ... }
|
把可能为空的变量编程不能为空的变量
1 2 3
| val data = ...
val mapped = data?.let { transformData(it) } ?: defaultValueIfDataIsNull
|
when 语句 作为一个表达式返回
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") } }
|
try/catch 也可以作为表达式,有返回值
1 2 3 4 5 6 7 8 9
| fun test() { val result = try { count() } catch (e: ArithmeticException) { throw IllegalStateException(e) }
}
|
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" } }
|
对于返回值为 Unit 的函数,可以使用构造器的风格调用
1 2 3 4 5 6
| fun arrayOfMinusOnes(size: Int): IntArray { return IntArray(size).apply { fill(-1) ... } }
|
现在我才知道,这个 apply 的高能,它就是为了方便对一个对象做一些配置,来个更好的栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| data class Person(var name: String, var age: Int) { fun wearHat() { }
fun wearCoat() { } }
....
val goodMan = Person("Jin", 27).apply { wearHat() wearCoat() }
|
单一表达式的函数
这个栗子也太简单了,因为 Kotlin 里 If 语句, When 语句, try/catch 语句 都是表达式,所以你懂得。
使用 “with” 在同一个对象上调用多个方法
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) { penDown() for(i in 1..4) { forward(100.0) turn(90.0) } penUp() }
|
感觉这和前边那个 apply 类似,都是在一个代码块里,this变成了我们指定的一个对象。不过使用 with 更有过程编程的感觉。
Java7 的 try-with-resources 在 Kotlin 里也有类似的实现
1 2 3 4
| val stream = Files.newInputStream(Paths.get("/some/file.txt")) stream.buffered().reader().use { reader -> println(reader.readText()) }
|
而 Java7 的 try-with-resource 是这样的
1 2 3 4
| try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); }
|
还是 Kotlin 的比较好看
对于一个需要泛型类型信息的泛型函数的方便方式
1 2 3 4 5 6
|
inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)
|
我对泛型还真是不太了解,暂不评价,我该去学习泛型了。
一个可能为 null 的 Boolean 也能直接被 if 条件判断
1 2 3 4 5 6
| val b: Boolean? = ... if (b == true) { ... } else { }
|
以下是一些缩写,有兴趣可以 wiki 一下:
- DTO – Data Transfer Object
- POJO – Plain old Java Object
- POCO – Plain Old CLR Object
- CLR – Comman Language Runtime