格式化
大括号
当when
分支和if
语句体没有其他分支如else if/else
时,可不需要大括号。
if (string.isEmpty()) return
when (value) {
0 -> return
// …
}
对于任何分支如if、for、when分支,do和while语句,必须有大括号,即使当主体是空的或仅包含一条语句。
if (string.isEmpty())
return // WRONG!
if (string.isEmpty()) {
return // Okay
}
非空语句块
按照Kernighan和Ritchie style (“Egyptian brackets”)的非空的块和块结构遵循如下:
- 左大括号(
{
)前不换行。 - 左大括号后换行。
- 右大括(
}
)号前换行。 - 右大括号后换行,只有在括号结束一条语句或终止函数体、构造方法或命名类才换行。例如后面跟着
else
或逗号则不换行。
return Runnable {
while (condition()) {
foo()
}
}
return object : MyClass() {
override fun foo() {
if (condition()) {
try {
something()
} catch (e: ProblemException) {
recover()
}
} else if (otherCondition()) {
somethingElse()
} else {
lastThing()
}
}
}
少部分如enum classes特例在后面给出。
空语句块
空块或类似块的结构必须是K&R样式。
try {
doSomething()
} catch (e: Exception) {} // WRONG!
try {
doSomething()
} catch (e: Exception) {
} // Okay
表达式
作为表达式使用的if / if条件只能在整个表达式匹配一行时省略括号。
val value = if (string.isEmpty()) 0 else 1 // Okay
val value = if (string.isEmpty()) // WRONG!
0
else
1
val value = if (string.isEmpty()) { // Okay
0
} else {
1
}
缩进
每次开始一个新的块或块结构时,缩进将增加四个空格。当块结束时,缩进返回到前一个缩进级别。缩进级别适用于整个块中的代码和注释。
每行一条语句
每个语句后面都有换行符。不使用分号。
断行
代码的行长度制为100个字符。除下文所示外,任何超出该限制的行都必须是断行的,如下所述。
例子:
- 不可能遵守列的长度限制的行(例如,一个KDoc中很长的URL)
package
和import
语句- 可以剪切并粘贴到shell中的注释中的命令行
应该何处断行
换行的主要原则是:倾向于在较高的语法层次上进行分解。或者:
- 在非赋值运算符中断开时,中断先于符号。
- 这也适用于下面的“操作符”符号:
- 点分隔符(
.
) - 两个冒号(
::
)
- 点分隔符(
- 这也适用于下面的“操作符”符号:
- 运算符断行时,中断是在符号之后。
- 方法或构造函数名附加在它后面的左括号(
(
)上。 - 逗号(
,
)与它前面的符号连接。 - lambda表达式箭头(
->
)与前面的参数列表连接。
注意:换行的主要目的是要有清晰的代码,而不一定是最少量的代码。
连续缩进
断行时,第一行之后的每一行(每个续行)从原行缩进至少8个空格。
当有多个连续行时,缩进可能会超出所需的8个以上空格。总的来说,属于同一条语句的两续行使用相同的缩进层次。
函数
当函数签名不适合于一行时,将每个参数声明中断到自己的行上。参数应使用连续缩进(+ 8)。右括号()
)和返回类型放在同一行上且不需要缩进。
fun <T> Iterable<T>.joinToString(
separator: CharSequence = ", ",
prefix: CharSequence = "",
postfix: CharSequence = ""
): String {
// …
}
表达式函数
当一个函数只包含一个表达式时,它可以表示为一个表达式函数。
override fun toString(): String {
return "Hey"
}
override fun toString(): String = "Hey"
表达式函数不应换行。如果表达式函数增长需要包装,则使用正常函数体、返回声明和常规表达式包装规则代替。