Kotlin Reference(一)-入门指南

Kotlin Reference(一)-入门指南

标签(空格分隔): 翻译 kotlin
翻译:陈小默
版权声明:禁止商用 转载请注明出处
原文地址:http://kotlinlang.org/docs/reference


  • Kotlin Reference一-入门指南
  • 基础语法
    • 包结构定义
    • 方法定义
    • 定义局部变量
    • 注释
    • 使用字符串模板输出
    • 使用条件表达式
    • 使用可能为null的值进行空值检查
    • 使用类型检查和自动转型
    • 使用for循环
    • 使用while循环
    • 使用when表达式
    • 使用区间
    • 使用集合
  • 代码风格
    • 创建DTOs POJOsPOCOs对象
    • 方法参数的默认值
    • 过滤一个List
    • 遍历MapList
    • 使用区间
    • 只读的List
    • 只读的Map
    • 访问一个Map
    • 懒汉性质
    • 功能扩展
    • 创建单例
    • 快捷判空
    • 快捷判空
    • 如果为空则执行声明
    • 如果不为空则执行操作
    • 在when条件语句中返回值
    • trycatch 表达式
    • if 表达式
    • Builder-style usage of methods that return Unit
    • 单行表达式的方法
    • 使用with可以调用对象的多个方法
    • Java 7s try with resources
    • 为声明泛型信息的泛型方法提供方便的格式
    • 使用可以为空的Boolean类型
  • 编码惯例
    • 命名风格
    • 冒号
    • Lambdas
    • Unit
    • Functions vs Properties

基础语法

包结构定义

定义的包信息必须在源文件的第一行

package my.demo

import java.util.*

//...

方法定义

定义一个具有两个Int类型参数和一个Int类型返回值的方法

fun sum(a: Int, b: Int): Int {
  return a + b
}

定义一个包含表达式,并且可以推论出返回值的方法

fun sum(a: Int, b: Int) = a + b

定义一个无意义类型Unit返回值的方法

fun printSum(a: Int, b: Int): Unit {
  print(a + b)
}

无意义类型Unit可以被忽略

fun printSum(a: Int, b: Int) {
  print(a + b)
}

定义局部变量

使用常量赋值

val a: Int = 1
val b = 1   // 隐式推断Int类型
val c: Int  // 未提供初始值时需要指定类型
c = 1       // 分配指定类型的值

使用变量赋值

var x = 5 // 隐式推断Int类型
x += 1

注释

就像Java和JavaScript那样,Kotlin同样支持单行注释和块注释

// 这是单行注释

/* 这是一个分布在
    /*这是一个嵌入的块注释*/
   多行的块注释 */

和Java不同的是,Kotlin的块注释允许嵌套

使用字符串模板输出

fun main(args: Array<String>) {
  if (args.size == 0) return

  print("First argument: ${args[0]}")
}

使用条件表达式

fun max(a: Int, b: Int): Int {
  if (a > b)
    return a
  else
    return b
}

如果使用了if-else表达式

fun max(a: Int, b: Int) = if (a > b) a else b

使用可能为null的值进行空值检查

当一个引用被允许使用null的时候,必须使用nullable明确的标记

以下方法表示当str不能转换为Int类型时,返回null

fun parseInt(str: String): Int? {
  // ...
}

使用上述可能产生null的方法

fun main(args: Array<String>) {
  if (args.size < 2) {
    print("Two integers expected")
    return
  }

  val x = parseInt(args[0])
  val y = parseInt(args[1])

  // x*y 操作会因为他们持有空值而产生错误
  if (x != null && y != null) {
    // 一旦经过非空检查操作,x和y就会被自动标记为非空
    print(x * y)
  }
}

或者

  // ...
  if (x == null) {
    print("Wrong number format in '${args[0]}'")
    return
  }
  if (y == null) {
    print("Wrong number format in '${args[1]}'")
    return
  }

  // 一旦经过非空检查操作,x和y就会被自动标记为非空
  print(x * y)

使用类型检查和自动转型

如果一个表达式是某一个类型的实例,则这个表达式的类型需要操作者手动检查。一旦一个不可变的本地变量或者属性的类型被查出,就不需要去明确的转型了。

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
    // obj在此代码块中被自动转型为String
    return obj.length
  }

  // 离开了上述if代码块,obj仍然是一个不受检查的Any类型
  return null
}

或者

fun getStringLength(obj: Any): Int? {
  if (obj !is String)
    return null

  // obj在此代码块中被自动转型为String
  return obj.length
}

甚至

fun getStringLength(obj: Any): Int? {
  // obj在’&&‘的右表达式中被自动转型为String
  if (obj is String && obj.length > 0)
    return obj.length

  return null
}

使用for循环

fun main(args: Array<String>) {
  for (arg in args)
    print(arg)
}

或者

for (i in args.indices)
  print(args[i])

使用while循环

fun main(args: Array<String>) {
    var i = 0
    while (i < args.size)
        print(args[i++])
}

使用when表达式

fun cases(obj: Any) {
  when (obj) {
    1          -> print("One")
    "Hello"    -> print("Greeting")
    is Long    -> print("Long")
    !is String -> print("Not a string")
    else       -> print("Unknown")
  }
}

使用区间

使用如下操作检查一个数字是否在某个区间内

if (x in 1..y-1)
  print("OK")

检查一个数字是否在区间之外

if (x !in 0..array.lastIndex)
  print("Out")

遍历一个区间

for (x in 1..5)
  print(x)

使用集合

遍历一个集合

for (name in names)
  println(name)

使用以下操作检查集合内是否包含特定对象

if (text in names) // names.contains(text) is called
  print("Yes")

使用lambda表达式去过滤和映射一个集合

names
    .filter { it.startsWith("A") }
    .sortedBy { it }
    .map { it.toUpperCase() }
    .forEach { print(it) }

代码风格

这里收集了常用的和不常用的Kotlin代码风格。如果你有好的代码风格,请在GitHub上使用pull request贡献给我们。

创建DTOs (POJOs/POCOs)对象

data class Customer(val name: String, val email: String)

上述操作提供了包含如下功能的Customer

    getters (and setters in case of vars) for all properties
    equals()
    hashCode()
    toString()
    copy()
    component1(), component2(), …, for all properties 

方法参数的默认值

fun foo(a: Int = 0, b: String = "") { ... }

过滤一个List

val positives = list.filter { x -> x > 0 }

或者提供一种更短的方式以供选择

val positives = list.filter { it > 0 }

使用$插入字符串

println("Name $name")

对象检查

when (x) {
    is Foo -> ...
    is Bar -> ...
    else   -> ...
}

遍历Map/List

for ((k, v) in map) {
    println("$k -> $v")
}

k, v 可以任意起名。

使用区间

for (i in 1..100) { ... }  // 闭区间: 包含 100
for (i in 1 until 100) { ... } // 开区间: 不包含100
for (x in 2..10 step 2) { ... } // 每次循环结束 自增2
for (x in 10 downTo 1) { ... } // 倒序循环
if (x in 1..10) { ... } // x 是否在区间内

只读的List

val list = listOf("a", "b", "c")

只读的Map

val map = mapOf("a" to 1, "b" to 2, "c" to 3)

访问一个Map

println(map["key"])
map["key"] = value

懒汉性质

val p: String by lazy {
    // compute the string
}

功能扩展

fun String.spaceToCamelCase() { ... }

"Convert this to camelcase".spaceToCamelCase()

创建单例

object Resource {
    val name = "Name"
}

快捷判空

val files = File("Test").listFiles()

println(files?.size)

快捷判空

val files = File("Test").listFiles()

println(files?.size ?: "empty")

如果为空则执行声明

val data = …
val email = data[“email”] ?: throw IllegalStateException(“Email is missing!”)

如果不为空则执行操作

val data = ...

data?.let {
    ... // execute this block if not null
}

在when条件语句中返回值

fun transform(color: String): Int {
    return when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}

‘try/catch’ 表达式

fun test() {
    val result = try {
        count()
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }

    // Working with result
}

‘if’ 表达式

fun foo(param: Int) {
    val result = if (param == 1) {
        "one"
    } else if (param == 2) {
        "two"
    } else {
        "three"
    }
}

Builder-style usage of methods that return Unit

fun arrayOfMinusOnes(size: Int): IntArray {
    return IntArray(size).apply { fill(-1) }
}

单行表达式的方法

fun theAnswer() = 42

等价于

fun theAnswer(): Int {
    return 42
}

以下能高效整合其他代码风格,产生更加简洁的代码

fun transform(color: String): Int = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

使用with可以调用对象的多个方法

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’s try with resources

val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
    println(reader.readText())
}

为声明泛型信息的泛型方法提供方便的格式

//  public final class Gson {
//     ...
//     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
//     ...

inline fun T: Any> Gson.fromJson(json): T = this.fromJson(json, T::class.java)

使用可以为空的Boolean类型

val b: Boolean? = ...
if (b == true) {
    ...
} else {
    // `b` is false or null
}

编码惯例

此页面包含当前Kotlin语言的编码风格

命名风格

Java的编码惯例:

  • 使用驼峰命名法
  • 类的首字母大写
  • 方法和属性的首字母小写
  • 使用4个空格缩进
  • 公共方法需要添加文档注释

冒号

如果冒号的作用是分隔类型和父类型则需要在冒号前面添加空格;如果是分隔实例和类型则不需要添加空格

interface Foo<out T : Any> : Bar {
    fun foo(a: Int): T
}

Lambdas

在Lambda表达式中,空格被用来分隔花括号,同样的,空格也被用来包裹分隔参数和函数体的剪头

list.filter { it > 10 }.map { element -> element * 2 }

推荐当lambda表达式比较短而且额没有嵌套时使用传统惯例而不是明确生命参数。

Unit

当函数返回值为Unit类型时,返回值类型的声明可以忽略

fun foo() { // ": Unit" is omitted here

}

Functions vs Properties

在通常情况下,没有参数的函数可以与只读属性替换。

满足下列规则时可以互换方法和属性

  • 没有抛出异常
  • 复杂度为0(1)
  • 简单的计算
  • 相同的返回值

你可能感兴趣的:(Kotlin Reference(一)-入门指南)