[TOC]
## internal
在 Kotlin 中,`internal` 关键字用于指定类、对象、接口、构造函数、属性、函数等的可见性范围。被标记为 `internal` 的成员只能在同一个模块中访问。模块的概念可以是一个 IntelliJ IDEA 模块、一个 Maven 项目、一个 Gradle 源集等。
### `internal` 关键字的作用和使用场景
1. **限制可见性范围**: `internal` 关键字限制了成员的可见性范围,使其只能在同一个模块内访问。这对于控制代码的访问范围、提高封装性和避免意外的使用非常有用。
2. **模块级别的访问控制**: 它允许开发者在模块内共享实现细节,但隐藏这些实现细节不被外部模块看到。例如,某些类或函数在模块内是必要的,但不希望它们被其他模块依赖和使用时,可以使用 `internal`。
3. **提高代码的可维护性**: 通过限制访问范围,可以减少模块间的耦合,提高代码的可维护性和重构的灵活性。
## actual
在 Kotlin 中,`actual` 关键字用于多平台项目中的期望(expect)/实际(actual)机制。这种机制允许你在不同的平台(如 JVM、JS、Native 等)中编写特定于平台的实现,同时共享公共代码。
### 期望和实际的工作机制
1. **期望声明** (`expect`):在共享模块中声明一个期望的类、函数或属性,而不提供具体实现。
2. **实际实现** (`actual`):在具体平台的模块中提供对应的实现。
### 示例:
1. 定义期望声明
```kotlin
// commonMain/src/commonMain/kotlin/com/example/Platform.kt
package com.example
expect class Platform() {
val name: String
}
```
2. 提供实际实现
JVM平台实现:
```kotlin
// jvmMain/src/jvmMain/kotlin/com/example/Platform.kt
package com.example
actual class Platform {
actual val name: String = "JVM"
}
```
JS 平台实现:
```kotlin
// jsMain/src/jsMain/kotlin/com/example/Platform.kt
package com.example
actual class Platform {
actual val name: String = "JS"
}
```
## typealias
在 Kotlin 中,`typealias` 关键字用于为现有类型定义一个新的别名。这可以使代码更具可读性,尤其是在处理长或复杂类型时。通过使用类型别名,可以简化类型引用,使代码更清晰、更易于维护。
```kotlin
typealias MyMapType = Map<String, List<Pair<Int, String>>>
val map: MyMapType = ...
```
## reified
在 Kotlin 中,`reified` 关键字用于内联函数(`inline` functions),使得在运行时能够访问泛型参数的具体类型。这是一个非常有用的特性,因为通常在 JVM 上,泛型类型信息在编译时会被擦除(type erasure),而 `reified` 关键字能够保留和使用这些类型信息。
```kotlin
fun <T> parseJson(json: String, clazz: Class<T>): T {
// 使用传入的 Class 对象进行解析
return Gson().fromJson(json, clazz)
}
// 使用时
val user = parseJson(jsonString, User::class.java)
```
## inline
在 Kotlin 中,`inline` 关键字用于内联函数。内联函数的主要作用是避免因函数调用而产生的开销,通过在编译时将函数的字节码直接插入到调用处,来减少运行时的开销。这对于某些场景下的性能优化非常有用,尤其是在高频率调用的函数中。
### 使用场景
* **高频调用的小函数**:如高阶函数、lambda 表达式等。
* **需要保留泛型类型信息的函数**:与 `reified` 泛型参数配合使用。
* **消除闭包开销**:当 lambda 表达式捕获了上下文中的变量时,会产生闭包对象。内联函数可以减少这些闭包的创建。
## noinline
在 Kotlin 中,`noinline` 关键字用于修饰内联函数的参数,使其在内联函数体内不被内联。通常与 `inline` 关键字配合使用。默认情况下,内联函数的所有 lambda 参数都会被内联,而有时我们希望某些 lambda 参数不要被内联,此时就可以使用 `noinline` 关键字。
### 使用场景
* **部分参数不内联**:在某些情况下,出于性能或代码结构的考虑,你可能希望内联函数的某些 lambda 参数不被内联。
* **延迟执行的 lambda**:当 lambda 参数需要在内联函数之外的上下文中被使用或传递时,需要使用 `noinline`。
```kotlin
inline fun process(
inlineLambda: () -> Unit,
noinline deferredLambda: () -> Unit
) {
inlineLambda()
executeLater(deferredLambda)
}
fun executeLater(action: () -> Unit) {
// Simulate some delay
Thread.sleep(1000)
action()
}
fun main() {
process(
inlineLambda = { println("Executing inline lambda immediately") },
deferredLambda = { println("Executing noinline lambda later") }
)
}
```
## crossinline
在Kotlin中,`crossinline`关键字用于修饰高阶函数的参数,以确保这些参数在内联(inline)时不会被非局部返回(non-local returns)打断。
使用`crossinline`修饰的参数不允许非局部返回。这对于确保传递的lambda表达式不能意外地中断包含它的内联函数非常重要。这在某些情况下是必要的,特别是在高阶函数的实现中,例如在异步执行或多线程环境中。
示例代码:
```kotlin
inline fun inlineFunction(block: () -> Unit) {
// 调用传递的lambda
block()
}
fun callerFunction() {
inlineFunction {
// 非局部返回
return
}
println("This will not be printed")
}
```
在上述代码中,`inlineFunction`是一个内联函数,接受一个`block`参数。`block`参数可以进行非局部返回,从而使得`callerFunction`函数在lambda中执行返回操作后直接退出。
```kotlin
inline fun inlineFunction(crossinline block: () -> Unit) {
// 调用传递的lambda
block()
}
fun callerFunction() {
inlineFunction {
// 非局部返回将导致编译错误
// return // This line will cause a compile-time error
println("Inside lambda")
}
println("This will be printed")
}
```
在这个例子中,通过在参数前添加`crossinline`关键字,`block`参数不允许非局部返回。如果尝试在lambda表达式中执行`return`操作,将会导致编译错误。
## infix
在 Kotlin 中,`infix` 关键字用于定义中缀函数(infix functions)。中缀函数是一种特殊的成员函数或扩展函数,它们可以以中缀表示法(即不使用点和括号)调用,从而提高代码的可读性和简洁性。使用 `infix` 关键字定义的函数必须满足以下条件:
1. 它是成员函数或扩展函数。
2. 它只有一个参数。
3. 它用 `infix` 关键字修饰。
```kotlin
infix fun Int.times(str: String): String {
return str.repeat(this)
}
fun main() {
val result = 3 times "Hello "
println(result) // 输出: Hello Hello Hello
}
```
## sealed
在 Kotlin 中,`sealed` 关键字用于声明密封类(sealed class)。密封类是一种特殊的类,可以有多个子类,但这些子类必须声明在同一个文件中。密封类的主要目的是限制继承的可能性,从而更好地控制类层次结构,并在使用 `when` 表达式时提供更强的类型安全性。
### 特性和用法
1. **密封类声明**: 使用 `sealed` 关键字来声明一个密封类。
2. **限制继承**: 密封类的所有直接子类必须声明在同一个文件中,但它们可以声明为嵌套类或者在文件的其他位置声明。
3. **提高 `when` 表达式的安全性**: 使用 `when` 表达式处理密封类时,如果分支覆盖了所有可能的子类,编译器将不会要求添加 `else` 分支。
```kotlin
sealed class Result
data class Success(val data: String) : Result()
data class Failure(val error: String) : Result()
object Loading : Result()
```
- 写在前面的话
- Java
- 基础
- Double的比较
- 小数怎么用二进制表示
- 多线程
- 并发和并行
- 线程池
- 线程池背景
- 线程池构造
- 任务阻塞队列
- Flutter
- 基础知识
- Dart基础
- Android
- 项目架构
- View
- 非UI线程更新View
- AlarmManager
- 对比postDelaryed和Timer
- Bitmap
- 加载100M的图片却不撑爆内存
- Bitmap压缩
- Bitmap局部解码
- 计算图片的内存占用
- Android动画
- Android动画类型
- Android动画原理
- 属性动画
- 帧动画
- 补间动画
- 使用动画的注意事项
- Android新特性
- 权限组
- Android23(Marshmallow)-6.0
- Android24(Nougat)-7.0
- Android26(Oreo)-8.0
- Android28(Pie)-9.0
- Android29(Q)-10.0
- AndroidX迁移
- Kotlin
- 关键字
- Kotlin操作符
- CoroutineScope
- Flow
- CoroutineException