# 編碼規范
本頁包含當前 Kotlin 語言的編碼風格。
[TOC]
### 應用風格指南
如需根據本風格指南配置 IntelliJ 格式化程序,請安裝 Kotlin 插件1.2.20 或更高版本,轉到 __Settings | Editor | Code Style | Kotlin__,點擊右上角的 __Set from...__ 鏈接,并從菜單中選擇 __Predefined style | Kotlin style guide__。
如需驗證代碼已按風格指南格式化,請轉到探查設置(Inspections)并啟用__Kotlin | Style issues | File is not formatted according to project settings__ 探查項。
驗證風格指南中描述的其他問題(如命名約定)的附加探查項默認已啟用。
## 源代碼組織
### 目錄結構
在純 Kotlin 項目中,推薦的目錄結構遵循省略了公共根包的包結構。例如,如果項目中的所有代碼都位于`org.example.kotlin` 包及其子包中,那么 `org.example.kotlin` 包的文件應該直接放在源代碼根目錄下,而`org.example.kotlin.network.socket` 中的文件應該放在源代碼根目錄下的 `network/socket` 子目錄中。
> **對于 JVM 平臺**:Kotlin 源文件應當與 Java 源文件位于同一源文件根目錄下,并遵循相同的目錄結構(每個文件應存儲在與其 package 語句對應的目錄中。
### 源文件名稱
如果 Kotlin 文件包含單個類(以及可能相關的頂層聲明),那么文件名應該與該類的名稱相同,并追加 .kt 擴展名。如果文件包含多個類或只包含頂層聲明,那么選擇一個描述該文件所包含內容的名稱,并以此命名該文件。使用首字母大寫的駝峰風格(例如 `ProcessDeclarations.kt`)。
文件的名稱應該描述文件中代碼的作用。因此,應避免在文件名中使用諸如“Util”之類的無意義詞語。
### 源文件組織
鼓勵多個聲明(類、頂級函數或者屬性)放在同一個 Kotlin 源文件中,只要這些聲明在語義上彼此緊密關聯并且文件保持合理大小(不超過幾百行)。
特別是在為類定義與類的所有客戶都相關的擴展函數時,請將它們放在與類自身定義相同的地方。而在定義僅對指定客戶有意義的擴展函數時,請將它們放在緊挨該客戶代碼之后。不要只是為了保存“Foo 的所有擴展函數”而創建文件。
### 類布局
通常,一個類的內容按以下順序排列:
- 屬性聲明與初始化塊
- 次構造函數
- 方法聲明
- 伴生對象
不要按字母順序或者可見性對方法聲明排序,也不要將常規方法與擴展方法分開。而是要把相關的東西放在一起,這樣從上到下閱讀類的人就能夠跟進所發生事情的邏輯。選擇一個順序(高級別優先,或者相反)并堅持下去。
將嵌套類放在緊挨使用這些類的代碼之后。如果打算在外部使用嵌套類,而且類中并沒有引用這些類,那么把它們放到末尾,在伴生對象之后。
### 接口實現布局
在實現一個接口時,實現成員的順序應該與該接口的成員順序相同(如果需要,還要插入用于實現的額外的私有方法)
### 重載布局
在類中總是將重載放在一起。
## 命名規則
在 Kotlin 中,包名與類名的命名規則非常簡單:
* 包的名稱總是小寫且不使用下劃線(`org.example.project`)。
通常不鼓勵使用多個詞的名稱,但是如果確實需要使用多個詞,可以將它們連接在一起或使用駝峰(`org.example.myProject`)。
* 類與對象的名稱以大寫字母開頭并使用駝峰:
```kotlin
open class DeclarationProcessor { …… }
object EmptyDeclarationProcessor : DeclarationProcessor() { …… }
```
### 函數名
函數、屬性與局部變量的名稱以小寫字母開頭、使用駝峰而不使用下劃線:
```kotlin
fun processDeclarations() { …… }
var declarationCount = ……
```
例外:用于創建類實例的工廠函數可以與要創建的類具有相同的名稱:
```kotlin
abstract class Foo { …… }
class FooImpl : Foo { …… }
fun Foo(): Foo { return FooImpl(……) }
```
#### 測試方法的名稱
當且僅當在測試中,可以使用反引號括起來的帶空格的方法名。(請注意,Android 運行時目前不支持這樣的方法名。)測試代碼中也允許方法名使用下劃線。
```kotlin
class MyTestCase {
@Test fun `ensure everything works`() { ... }
@Test fun ensureEverythingWorks_onAndroid() { ... }
}
```
### 屬性名
常量名稱(標有 `const` 的屬性,或者保存不可變數據的沒有自定義 `get` 函數的頂層/對象 `val` 屬性)應該使用大寫、下劃線分隔的名稱:
```kotlin
const val MAX_COUNT = 8
val USER_NAME_FIELD = "UserName"
```
保存帶有行為的對象或者可變數據的頂層/對象屬性的名稱應該使用常規駝峰名稱:
```kotlin
val mutableCollection: MutableSet<String> = HashSet()
```
保存單例對象引用的屬性的名稱可以使用與 `object` 聲明相同的命名風格:
```kotlin
val PersonComparator: Comparator<Person> = ...
```
對于枚舉常量,可以使用大寫、下劃線分隔的名稱
(`enum class Color { RED, GREEN }`)也可使用以大寫字母開頭的常規駝峰名稱,具體取決于用途。
#### 幕后屬性的名稱
如果一個類有兩個概念上相同的屬性,一個是公共 API 的一部分,另一個是實現細節,那么使用下劃線作為私有屬性名稱的前綴:
```kotlin
class C {
private val _elementList = mutableListOf<Element>()
val elementList: List<Element>
get() = _elementList
}
```
### 選擇好名稱
類的名稱通常是用來解釋類*是*什么的名詞或者名詞短語:`List`、 `PersonReader`。
方法的名稱通常是動詞或動詞短語,說明該方法*做*什么:`close`、 `readPersons`。
修改對象或者返回一個新對象的名稱也應遵循建議。例如 `sort` 是對一個集合就地排序,而 `sorted` 是返回一個排序后的集合副本。
名稱應該表明實體的目的是什么,所以最好避免在名稱中使用無意義的單詞(`Manager`、 `Wrapper` 等)。
當使用首字母縮寫作為名稱的一部分時,如果縮寫由兩個字母組成,就將其大寫(`IOStream`);
而如果縮寫更長一些,就只大寫其首字母(`XmlFormatter`、 `HttpInputStream`)。
## 格式化
使用 4 個空格縮進。不要使用 tab。
對于花括號,將左花括號放在結構起始處的行尾,而將右花括號放在與左括結構橫向對齊的單獨一行
```kotlin
if (elements != null) {
for (element in elements) {
// ……
}
}
```
>[info]注意:在 Kotlin 中,分號是可選的,因此換行很重要。語言設計采用Java 風格的花括號格式,如果嘗試使用不同的格式化風格,那么可能會遇到意外的行為。
### 橫向空白
在二元操作符左右留空格(`a + b`)。例外:不要在“range to”操作符(`0..i`)左右留空格。
不要在一元運算符左右留空格(`a++`)
在控制流關鍵字(`if`、 `when`、 `for` 以及 `while`)與相應的左括號之間留空格。
不要在主構造函數聲明、方法聲明或者方法調用的左括號之前留空格。
```kotlin
class A(val x: Int)
fun foo(x: Int) { …… }
fun bar() {
foo(1)
}
```
絕不在 `(`、 `[` 之后或者 `]`、 `)` 之前留空格。
絕不在`.` 或者 `?.` 左右留空格:`foo.bar().filter { it > 2 }.joinToString()`, `foo?.bar()`
在 `//` 之后留一個空格:`// 這是一條注釋`
不要在用于指定類型參數的尖括號前后留空格:`class Map<K, V> { …… }`
不要在 `::` 前后留空格:`Foo::class`、 `String::length`
不要在用于標記可空類型的 `?` 前留空格:`String?`
作為一般規則,避免任何類型的水平對齊。將標識符重命名為不同長度的名稱不應該影響聲明或者任何用法的格式。
### 冒號
在以下場景中的 `:` 之前留一個空格:
* 當它用于分隔類型與超類型時;
* 當委托給一個超類的構造函數或者同一類的另一個構造函數時;
* 在 `object` 關鍵字之后。
而當分隔聲明與其類型時,不要在 `:` 之前留空格。在 `:` 之后總要留一個空格。
```kotlin
abstract class Foo<out T : Any> : IFoo {
abstract fun foo(a: Int): T
}
class FooImpl : Foo() {
constructor(x: String) : this(x) { …… }
val x = object : IFoo { …… }
}
```
### 類頭格式化
具有少數主構造函數參數的類可以寫成一行:
```kotlin
class Person(id: Int, name: String)
```
具有較長類頭的類應該格式化,以使每個主構造函數參數都在帶有縮進的獨立的行中。另外,右括號應該位于一個新行上。如果使用了繼承,那么超類的構造函數調用或者所實現接口的列表應該與右括號位于同一行:
```kotlin
class Person(
id: Int,
name: String,
surname: String
) : Human(id, name) { …… }
```
對于多個接口,應該將超類構造函數調用放在首位,然后將每個接口應放在不同的行中:
```kotlin
class Person(
id: Int,
name: String,
surname: String
) : Human(id, name),
KotlinMaker { …… }
```
對于具有很長超類型列表的類,在冒號后面換行,并橫向對齊所有超類型名:
```kotlin
class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne {
fun foo() { ... }
}
```
為了將類頭與類體分隔清楚,當類頭很長時,可以在類頭后放一空行(如上例所示)或者將左花括號放在獨立行上:
```kotlin
class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne
{
fun foo() { ... }
}
```
構造函數參數使用常規縮進(4 個空格)。
> 理由:這確保了在主構造函數中聲明的屬性與
在類體中聲明的屬性具有相同的縮進。
### 修飾符
如果一個聲明有多個修飾符,請始終按照以下順序安放:
```kotlin
public / protected / private / internal
expect / actual
final / open / abstract / sealed / const
external
override
lateinit
tailrec
vararg
suspend
inner
enum / annotation
companion
inline
infix
operator
data
```
將所有注解放在修飾符前:
```kotlin
@Named("Foo")
private val foo: Foo
```
除非你在編寫庫,否則請省略多余的修飾符(例如 `public`)。
### 注解格式化
注解通常放在單獨的行上,在它們所依附的聲明之前,并使用相同的縮進:
```
@Target(AnnotationTarget.PROPERTY)
annotation class JsonExclude
```
無參數的注解可以放在同一行:
```kotlin
@JsonExclude @JvmField
var x: String
```
無參數的單個注解可以與相應的聲明放在同一行:
```kotlin
@Test fun foo() { …… }
```
### 文件注解
文件注解位于文件注釋(如果有的話)之后、`package` 語句之前,并且用一個空白行與 `package` 分開(為了強調其針對文件而不是包)。
```kotlin
/** 授權許可、版權以及任何其他內容 */
@file:JvmName("FooBar")
package foo.bar
```
### 函數格式化
如果函數簽名不適合單行,請使用以下語法:
```kotlin
fun longMethodName(
argument: ArgumentType = defaultValue,
argument2: AnotherArgumentType
): ReturnType {
// 函數體
}
```
函數參數使用常規縮進(4 個空格)。
> 理由:與構造函數參數一致
對于由單個表達式構成的函數體,優先使用表達式形式。
```kotlin
fun foo(): Int { // 不良
return 1
}
fun foo() = 1 // 良好
```
### 表達式函數體格式化
如果函數的表達式函數體與函數聲明不適合放在同一行,那么將 `=` 留在第一行。將表達式函數體縮進 4 個空格。
```kotlin
fun f(x: String) =
x.length
```
### 屬性格式化
對于非常簡單的只讀屬性,請考慮單行格式:
```kotlin
val isEmpty: Boolean get() = size == 0
```
對于更復雜的屬性,總是將 `get` 與 `set` 關鍵字放在不同的行上:
```kotlin
val foo: String
get() { …… }
```
對于具有初始化器的屬性,如果初始化器很長,那么在等號后增加一個換行<并將初始化器縮進四個空格:
```kotlin
private val defaultCharset: Charset? =
EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
```
### 格式化控制流語句
如果 `if` 或 `when` 語句的條件有多行,那么在語句體外邊總是使用大括號。
將該條件的每個后續行相對于條件語句起始處縮進 4 個空格。
將該條件的右圓括號與左花括號放在單獨一行:
```kotlin
if (!component.isSyncing &&
!hasAnyKotlinRuntimeInScope(module)
) {
return createKotlinNotConfiguredPanel(module)
}
```
> 理由:對齊整齊并且將條件與語句體分隔清楚
將 `else`、 `catch`、 `finally` 關鍵字以及 do/while 循環的 `while` 關鍵字與之前的花括號放在相同的行上:
```kotlin
if (condition) {
// 主體
} else {
// else 部分
}
try {
// 主體
} finally {
// 清理
}
```
在 `when` 語句中,如果一個分支不止一行,可以考慮用空行將其與相鄰的分支塊分開:
```kotlin
private fun parsePropertyValue(propName: String, token: Token) {
when (token) {
is Token.ValueToken ->
callback.visitValue(propName, token.value)
Token.LBRACE -> { // ……
}
}
}
```
將短分支放在與條件相同的行上,無需花括號。
```kotlin
when (foo) {
true -> bar() // 良好
false -> { baz() } // 不良
}
```
### 方法調用格式化
在較長參數列表的左括號后添加一個換行符。按 4 個空格縮進參數。將密切相關的多個參數分在同一行。
```kotlin
drawSquare(
x = 10, y = 10,
width = 100, height = 100,
fill = true
)
```
在分隔參數名與值的 `=` 左右留空格。
### 鏈式調用換行
當對鏈式調用換行時,將 `.` 字符或者 `?.` 操作符放在下一行,并帶有單倍縮進:
```kotlin
val anchor = owner
?.firstChild!!
.siblings(forward = true)
.dropWhile { it is PsiComment || it is PsiWhiteSpace }
```
調用鏈的第一個調用通常在換行之前,當然如果能讓代碼更有意義也可以忽略這點。
### Lambda 表達式格式化
在 lambda 表達式中,應該在花括號左右以及分隔參數與代碼體的箭頭左右留空格。
如果一個調用接受單個 lambda 表達式,應該盡可能將其放在圓括號外邊傳入。
```kotlin
list.filter { it > 10 }
```
如果為 lambda 表達式分配一個標簽,那么不要在該標簽與左花括號之間留空格:
```kotlin
fun foo() {
ints.forEach lit@{
// ……
}
}
```
在多行的 lambda 表達式中聲明參數名時,將參數名放在第一行,后跟箭頭與換行符:
```kotlin
appendCommaSeparated(properties) { prop ->
val propertyValue = prop.get(obj) // ……
}
```
如果參數列表太長而無法放在一行上,請將箭頭放在單獨一行:
```kotlin
foo {
context: Context,
environment: Env
->
context.configureEnv(environment)
}
```
## 文檔注釋
對于較長的文檔注釋,將開頭 `/**` 放在一個獨立行中,并且后續每行都以星號開頭:
```kotlin
/**
* 這是一條多行
* 文檔注釋。
*/
```
簡短注釋可以放在一行內:
```kotlin
/** 這是一條簡短文檔注釋。 */
```
通常,避免使用 `@param` 與 `@return` 標記。而是將參數與返回值的描述直接合并到文檔注釋中,并在提到參數的任何地方加上參數鏈接。
只有當需要不適合放進主文本流程的冗長描述時才應使用 `@param` 與 `@return`。
```kotlin
// 避免這樣:
/**
* Returns the absolute value of the given number.
* @param number The number to return the absolute value for.
* @return The absolute value.
*/
fun abs(number: Int) = ……
// 而要這樣:
/**
* Returns the absolute value of the given [number].
*/
fun abs(number: Int) = ……
```
## 避免重復結構
一般來說,如果 Kotlin 中的某種語法結構是可選的并且被 IDE高亮為冗余的,那么應該在代碼中省略之。為了清楚起見,不要在代碼中保留不必要的語法元素。
### Unit
如果函數返回 Unit,那么應該省略返回類型:
```kotlin
fun foo() { // 這里省略了“: Unit”
}
```
### 分號
盡可能省略分號。
### 字符串模版
將簡單變量傳入到字符串模版中時不要使用花括號。只有用到更長表達式時才使用花括號。
```kotlin
println("$name has ${children.size} children")
```
## 語言特性的慣用法
### 不可變性
優先使用不可變(而不是可變)數據。初始化后未修改的局部變量與屬性,總是將其聲明為 `val` 而不是 `var`。
總是使用不可變集合接口(`Collection`, `List`, `Set`, `Map`)來聲明無需改變的集合。使用工廠函數創建集合實例時,盡可能選用返回不可變集合類型的函數:
```kotlin
// 不良:使用可變集合類型作為無需改變的值
fun validateValue(actualValue: String, allowedValues: HashSet<String>) { …… }
// 良好:使用不可變集合類型
fun validateValue(actualValue: String, allowedValues: Set<String>) { …… }
// 不良:arrayListOf() 返回 ArrayList<T>,這是一個可變集合類型
val allowedValues = arrayListOf("a", "b", "c")
// 良好:listOf() 返回 List<T>
val allowedValues = listOf("a", "b", "c")
```
### 默認參數值
優先聲明帶有默認參數的函數而不是聲明重載函數。
```kotlin
// 不良
fun foo() = foo("a")
fun foo(a: String) { …… }
// 良好
fun foo(a: String = "a") { …… }
```
### 類型別名
如果有一個在代碼庫中多次用到的函數類型或者帶有類型參數的類型,那么最好為它定義一個類型別名:
```kotlin
typealias MouseClickHandler = (Any, MouseEvent) -> Unit
typealias PersonIndex = Map<String, Person>
```
### Lambda 表達式參數
在簡短、非嵌套的 lambda 表達式中建議使用 `it` 用法而不是顯式聲明參數。而在有參數的嵌套 lambda 表達式中,始終應該顯式聲明參數。
### 在 lambda 表達式中返回
避免在 lambda 表達式中使用多個返回到標簽。請考慮重新組織這樣的 lambda 表達式使其只有單一退出點。
如果這無法做到或者不夠清晰,請考慮將 lambda 表達式轉換為匿名函數。
不要在 lambda 表達式的最后一條語句中使用返回到標簽。
### 命名參數
當一個方法接受多個相同的原生類型參數或者多個 `Boolean` 類型參數時,請使用命名參數語法,除非在上下文中的所有參數的含義都已絕對清楚。
```kotlin
drawSquare(x = 10, y = 10, width = 100, height = 100, fill = true)
```
### 使用條件語句
優先使用 `try`、`if` 與 `when` 的表達形式。例如:
```kotlin
return if (x) foo() else bar()
return when(x) {
0 -> "zero"
else -> "nonzero"
}
```
優先選用上述代碼而不是:
```kotlin
if (x)
return foo()
else
return bar()
when(x) {
0 -> return "zero"
else -> return "nonzero"
}
```
### `if` 還是 `when`
二元條件優先使用 `if` 而不是 `when`。不要使用
```kotlin
when (x) {
null -> ……
else -> ……
}
```
而應使用 `if (x == null) …… else ……`
如果有三個或多個選項時優先使用 `when`。
### 在條件中使用可空的 `Boolean` 值
如果需要在條件語句中用到可空的 `Boolean`, 使用 `if (value == true)` 或 `if (value == false)` 檢測。
### 使用循環
優先使用高階函數(`filter`、`map` 等)而不是循環。例外:`forEach`(優先使用常規的 `for` 循環,
除非 `forEach` 的接收者是可空的或者 `forEach` 用做長調用鏈的一部分。)
當在使用多個高階函數的復雜表達式與循環之間進行選擇時,請了解每種情況下所執行操作的開銷并且記得考慮性能因素。
### 區間上循環
使用 `until` 函數在一個開區間上循環:
```kotlin
for (i in 0..n - 1) { …… } // 不良
for (i in 0 until n) { …… } // 良好
```
### 使用字符串
優先使用字符串模板而不是字符串拼接。
優先使用多行字符串而不是將 `\n` 轉義序列嵌入到常規字符串字面值中。
如需在多行字符串中維護縮進,當生成的字符串不需要任何內部縮進時使用 `trimIndent`,而需要內部縮進時使用 `trimMargin`:
```kotlin
assertEquals(
"""
Foo
Bar
""".trimIndent(),
value
)
val a = """if(a > 1) {
| return a
|}""".trimMargin()
```
### 函數還是屬性
在某些情況下,不帶參數的函數可與只讀屬性互換。雖然語義相似,但是在某種程度上有一些風格上的約定。
底層算法優先使用屬性而不是函數:
* 不會拋異常
* 計算開銷小(或者在首次運行時緩存)
* 如果對象狀態沒有改變,那么多次調用都會返回相同結果
### 使用擴展函數
放手去用擴展函數。每當你有一個主要用于某個對象的函數時,可以考慮使其成為一個以該對象為接收者的擴展函數。為了盡量減少 API 污染,盡可能地限制擴展函數的可見性。根據需要,使用局部擴展函數、成員擴展函數或者具有私有可視性的頂層擴展函數。
### 使用中綴函數
一個函數只有用于兩個角色類似的對象時才將其聲明為中綴函數。良好示例如:`and`、 `to`、`zip`。不良示例如:`add`。如果一個方法會改動其接收者,那么不要聲明為中綴形式。
### 工廠函數
如果為一個類聲明一個工廠函數,那么不要讓它與類自身同名。優先使用獨特的名稱,該名稱能表明為何該工廠函數的行為與眾不同。只有當確實沒有特殊的語義時,才可以使用與該類相同的名稱。
例如:
```kotlin
class Point(val x: Double, val y: Double) {
companion object {
fun fromPolar(angle: Double, radius: Double) = Point(...)
}
}
```
如果一個對象有多個重載的構造函數,它們并非調用不同的超類構造函數,并且不能簡化為具有默認參數值的單個構造函數,那么優先用工廠函數取代這些重載的構造函數。
### 平臺類型
返回平臺類型表達式的公有函數/方法必須顯式聲明其 Kotlin 類型:
```kotlin
fun apiCall(): String = MyJavaApi.getProperty("name")
```
任何使用平臺類型表達式初始化的屬性(包級別或類級別)必須顯式聲明其 Kotlin 類型:
```kotlin
class Person {
val name: String = MyJavaApi.getProperty("name")
}
```
使用平臺類型表達式初始化的局部值可以有也可以沒有類型聲明:
```kotlin
fun main() {
val name = MyJavaApi.getProperty("name")
println(name)
}
```
### 使用作用域函數 apply/with/run/also/let
Kotlin 提供了一系列用來在給定對象上下文中執行代碼塊的函數:`let`、 `run`、 `with`、 `apply` 以及 `also`。
關于不同情況下選擇正確作用域函數的準則,請參考[作用域函數](scope-functions.html)。
## 庫的編碼規范
在編寫庫時,建議遵循一組額外的規則以確保 API 的穩定性:
* 總是顯式指定成員的可見性(以避免將聲明意外暴露為公有 API )
* 總是顯式指定函數返回類型以及屬性類型(以避免當實現改變時意外更改返回類型)
* 為所有公有成員提供 KDoc 注釋,不需要任何新文檔的覆蓋成員除外(以支持為該庫生成文檔)
- 前言
- Kotlin簡介
- IntelliJ IDEA技巧總結
- idea設置類注釋和方法注釋模板
- 像Android Studion一樣創建工程
- Gradle
- Gradle入門
- Gradle進階
- 使用Gradle創建一個Kotlin工程
- 環境搭建
- Androidstudio平臺搭建
- Eclipse的Kotlin環境配置
- 使用IntelliJ IDEA
- Kotlin學習路線
- Kotlin官方中文版文檔教程
- 概述
- kotlin用于服務器端開發
- kotlin用于Android開發
- kotlin用于JavaScript開發
- kotlin用于原生開發
- Kotlin 用于數據科學
- 協程
- 多平臺
- 新特性
- 1.1的新特性
- 1.2的新特性
- 1.3的新特性
- 開始
- 基本語法
- 習慣用法
- 編碼規范
- 基礎
- 基本類型
- 包與導入
- 控制流
- 返回與跳轉
- 類與對象
- 類與繼承
- 屬性與字段
- 接口
- 可見性修飾符
- 擴展
- 數據類
- 密封類
- 泛型
- 嵌套類
- 枚舉類
- 對象
- 類型別名
- 內嵌類
- 委托
- 委托屬性
- 函數與Lambda表達式
- 函數
- Lambda表達式
- 內聯函數
- 集合
- 集合概述
- 構造集合
- 迭代器
- 區間與數列
- 序列
- 操作概述
- 轉換
- 過濾
- 加減操作符
- 分組
- 取集合的一部分
- 取單個元素
- 排序
- 聚合操作
- 集合寫操作
- List相關操作
- Set相關操作
- Map相關操作
- 多平臺程序設計
- 平臺相關聲明
- 以Gradle創建
- 更多語言結構
- 解構聲明
- 類型檢測與轉換
- This表達式
- 相等性
- 操作符重載
- 空安全
- 異常
- 注解
- 反射
- 作用域函數
- 類型安全的構造器
- Opt-in Requirements
- 核心庫
- 標準庫
- kotlin.test
- 參考
- 關鍵字與操作符
- 語法
- 編碼風格約定
- Java互操作
- Kotlin中調用Java
- Java中調用Kotlin
- JavaScript
- 動態類型
- kotlin中調用JavaScript
- JavaScript中調用kotlin
- JavaScript模塊
- JavaScript反射
- JavaScript DCE
- 原生
- 并發
- 不可變性
- kotlin庫
- 平臺庫
- 與C語言互操作
- 與Object-C及Swift互操作
- CocoaPods集成
- Gradle插件
- 調試
- FAQ
- 協程
- 協程指南
- 基礎
- 取消與超時
- 組合掛起函數
- 協程上下文與調度器
- 異步流
- 通道
- 異常處理與監督
- 共享的可變狀態與并發
- Select表達式(實驗性)
- 工具
- 編寫kotlin代碼文檔
- 使用Kapt
- 使用Gradle
- 使用Maven
- 使用Ant
- Kotlin與OSGI
- 編譯器插件
- 編碼規范
- 演進
- kotlin語言演進
- 不同組件的穩定性
- kotlin1.3的兼容性指南
- 常見問題
- FAQ
- 與Java比較
- 與Scala比較(官方已刪除)
- Google開發者官網簡介
- Kotlin and Android
- Get Started with Kotlin on Android
- Kotlin on Android FAQ
- Android KTX
- Resources to Learn Kotlin
- Kotlin樣品
- Kotlin零基礎到進階
- 第一階段興趣入門
- kotlin簡介和學習方法
- 數據類型和類型系統
- 入門
- 分類
- val和var
- 二進制基礎
- 基礎
- 基本語法
- 包
- 示例
- 編碼規范
- 代碼注釋
- 異常
- 根類型“Any”
- Any? 可空類型
- 可空性的實現原理
- kotlin.Unit類型
- kotlin.Nothing類型
- 基本數據類型
- 數值類型
- 布爾類型
- 字符型
- 位運算符
- 變量和常量
- 語法和運算符
- 關鍵字
- 硬關鍵字
- 軟關鍵字
- 修飾符關鍵字
- 特殊標識符
- 操作符和特殊符號
- 算術運算符
- 賦值運算符
- 比較運算符
- 邏輯運算符
- this關鍵字
- super關鍵字
- 操作符重載
- 一元操作符
- 二元操作符
- 字符串
- 字符串介紹和屬性
- 字符串常見方法操作
- 字符串模板
- 數組
- 數組介紹創建及遍歷
- 數組常見方法和屬性
- 數組變化以及下標越界問題
- 原生數組類型
- 區間
- 正向區間
- 逆向區間
- 步長
- 類型檢測與類型轉換
- is、!is、as、as-運算符
- 空安全
- 可空類型變量
- 安全調用符
- 非空斷言
- Elvis操作符
- 可空性深入
- 可空性和Java
- 函數
- 函數式編程概述
- OOP和FOP
- 函數式編程基本特性
- 組合與范疇
- 在Kotlin中使用函數式編程
- 函數入門
- 函數作用域
- 函數加強
- 命名參數
- 默認參數
- 可變參數
- 表達式函數體
- 頂層、嵌套、中綴函數
- 尾遞歸函數優化
- 函數重載
- 控制流
- if表達式
- when表達式
- for循環
- while循環
- 循環中的 Break 與 continue
- return返回
- 標簽處返回
- 集合
- list集合
- list集合介紹和操作
- list常見方法和屬性
- list集合變化和下標越界
- set集合
- set集合介紹和常見操作
- set集合常見方法和屬性
- set集合變換和下標越界
- map集合
- map集合介紹和常見操作
- map集合常見方法和屬性
- map集合變換
- 集合的函數式API
- map函數
- filter函數
- “ all ”“ any ”“ count ”和“ find ”:對集合應用判斷式
- 別樣的求和方式:sumBy、sum、fold、reduce
- 根據人的性別進行分組:groupBy
- 扁平化——處理嵌套集合:flatMap、flatten
- 惰性集合操作:序列
- 區間、數組、集合之間轉換
- 面向對象
- 面向對象-封裝
- 類的創建及屬性方法訪問
- 類屬性和字段
- 構造器
- 嵌套類(內部類)
- 枚舉類
- 枚舉類遍歷&枚舉常量常用屬性
- 數據類
- 密封類
- 印章類(密封類)
- 面向對象-繼承
- 類的繼承
- 面向對象-多態
- 抽象類
- 接口
- 接口和抽象類的區別
- 面向對象-深入
- 擴展
- 擴展:為別的類添加方法、屬性
- Android中的擴展應用
- 優化Snackbar
- 用擴展函數封裝Utils
- 解決煩人的findViewById
- 擴展不是萬能的
- 調度方式對擴展函數的影響
- 被濫用的擴展函數
- 委托
- 委托類
- 委托屬性
- Kotlin5大內置委托
- Kotlin-Object關鍵字
- 單例模式
- 匿名類對象
- 伴生對象
- 作用域函數
- let函數
- run函數
- with函數
- apply函數
- also函數
- 標準庫函數
- takeIf 與 takeUnless
- 第二階段重點深入
- Lambda編程
- Lambda成員引用高階函數
- 高階函數
- 內聯函數
- 泛型
- 泛型的分類
- 泛型約束
- 子類和子類型
- 協變與逆變
- 泛型擦除與實化類型
- 泛型類型參數
- 泛型的背后:類型擦除
- Java為什么無法聲明一個泛型數組
- 向后兼容的罪
- 類型擦除的矛盾
- 使用內聯函數獲取泛型
- 打破泛型不變
- 一個支持協變的List
- 一個支持逆變的Comparator
- 協變和逆變
- 第三階段難點突破
- 注解和反射
- 聲明并應用注解
- DSL
- 協程
- 協程簡介
- 協程的基本操作
- 協程取消
- 管道
- 慕課霍丙乾協程筆記
- Kotlin與Java互操作
- 在Kotlin中調用Java
- 在Java中調用Kotlin
- Kotlin與Java中的操作對比
- 第四階段專題練習
- 朱凱Kotlin知識點總結
- Kotlin 基礎
- Kotlin 的變量、函數和類型
- Kotlin 里那些「不是那么寫的」
- Kotlin 里那些「更方便的」
- Kotlin 進階
- Kotlin 的泛型
- Kotlin 的高階函數、匿名函數和 Lambda 表達式
- Kotlin協程
- 初識
- 進階
- 深入
- Kotlin 擴展
- 會寫「18.dp」只是個入門——Kotlin 的擴展函數和擴展屬性(Extension Functions / Properties)
- Kotlin實戰-開發Android