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