2-2-37 快速掌握Kotlin-类型映射

28 阅读3分钟

Kotlin 类型映射(Type Mapping)详解

1. 基础类型映射

Kotlin 与 Java 基本类型映射

// Kotlin 使用对象类型,但在编译时会优化为基本类型
val int: Int = 42          // 对应 Java int/Integer
val long: Long = 42L       // 对应 Java long/Long
val double: Double = 3.14  // 对应 Java double/Double
val float: Float = 3.14f   // 对应 Java float/Float
val boolean: Boolean = true // 对应 Java boolean/Boolean
val char: Char = 'A'       // 对应 Java char/Character
val byte: Byte = 1         // 对应 Java byte/Byte
val short: Short = 1       // 对应 Java short/Short

可空类型映射

// Kotlin 的可空类型映射到 Java 的包装类型
val nullableInt: Int? = null        // 对应 Java Integer
val nullableLong: Long? = null      // 对应 Java Long
val nullableBoolean: Boolean? = null // 对应 Java Boolean

2. 集合类型映射

List 类型映射

// Kotlin List -> Java List/ArrayList
val kotlinList: List<String> = listOf("A", "B", "C")
// 对应 Java: List<String>

// Kotlin MutableList -> Java ArrayList
val mutableList: MutableList<String> = mutableListOf("A", "B", "C")
// 对应 Java: ArrayList<String>

// 与 Java 互操作
val javaList: java.util.List<String> = kotlinList  // 隐式转换
val kotlinFromJava: List<String> = javaList        // 隐式转换

Set 类型映射

// Kotlin Set -> Java Set/HashSet
val kotlinSet: Set<Int> = setOf(1, 2, 3)
// 对应 Java: Set<Integer>

val mutableSet: MutableSet<Int> = mutableSetOf(1, 2, 3)
// 对应 Java: HashSet<Integer>

Map 类型映射

// Kotlin Map -> Java Map/HashMap
val kotlinMap: Map<String, Int> = mapOf("a" to 1, "b" to 2)
// 对应 Java: Map<String, Integer>

val mutableMap: MutableMap<String, Int> = mutableMapOf("a" to 1)
// 对应 Java: HashMap<String, Integer>

3. 数组类型映射

基本类型数组

// Kotlin 特殊数组类
val intArray: IntArray = intArrayOf(1, 2, 3)          // 对应 Java int[]
val longArray: LongArray = longArrayOf(1L, 2L)        // 对应 Java long[]
val doubleArray: DoubleArray = doubleArrayOf(1.0, 2.0) // 对应 Java double[]
val booleanArray: BooleanArray = booleanArrayOf(true, false) // 对应 Java boolean[]
val charArray: CharArray = charArrayOf('a', 'b')      // 对应 Java char[]
val byteArray: ByteArray = byteArrayOf(1, 2)          // 对应 Java byte[]
val shortArray: ShortArray = shortArrayOf(1, 2)       // 对应 Java short[]
val floatArray: FloatArray = floatArrayOf(1.0f, 2.0f) // 对应 Java float[]

对象类型数组

// Array<T> 对应 Java T[]
val stringArray: Array<String> = arrayOf("a", "b")    // 对应 Java String[]
val nullableArray: Array<String?> = arrayOf("a", null) // 对应 Java String[]

// 创建指定大小的数组
val sizedArray = Array(5) { i -> "Item $i" }

数组转换

// List 转数组
val list = listOf(1, 2, 3)
val array1: Array<Int> = list.toTypedArray()
val intArray2: IntArray = list.toIntArray()

// 数组转 List
val array = arrayOf(1, 2, 3)
val listFromArray: List<Int> = array.toList()

4. 平台类型映射

Java 互操作中的平台类型

// Java 代码
public class JavaExample {
    public String getName() { return "John"; }  // @Nullable String
    public @NotNull String getTitle() { return "Mr."; }
    public List<String> getItems() { return Arrays.asList("a", "b"); }
}

// Kotlin 中使用
val example = JavaExample()
val name: String? = example.name     // 可空,因为Java方法可能返回null
val title: String = example.title    // 非空,因为@NotNull注解
val items: List<String> = example.items  // 平台类型 List<String>!

平台类型注解

// 使用注解明确平台类型
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable

// Kotlin 调用时
fun processJavaType(@Nullable nullableStr: String?) {
    // 明确处理可空性
}

fun processJavaType(@NotNull notNullStr: String) {
    // 可以安全调用
}

5. 函数类型映射

Kotlin 函数类型到 Java 接口

// Kotlin 函数类型
val kotlinFunction: (Int, String) -> Boolean = { i, s -> i > 0 && s.isNotEmpty() }

// 对应 Java 接口
// 实际上映射到 Function2<Integer, String, Boolean>

与 Java 函数式接口互操作

// Java 函数式接口
@FunctionalInterface
interface JavaProcessor {
    String process(String input);
}

// Kotlin 中使用
fun useJavaProcessor(processor: JavaProcessor) {
    val result = processor.process("test")
}

// 传递 lambda
useJavaProcessor { input -> input.uppercase() }

// SAM 转换
val processor = JavaProcessor { it.uppercase() }

6. 泛型类型映射

型变映射

// Java 通配符 ? extends T 和 ? super T
// Java: List<? extends Number> numbers

// Kotlin 中等价表示
val numbers: List<out Number> = listOf(1, 2.5, 3L)  // 协变
val consumer: MutableList<in String> = mutableListOf()  // 逆变

// 星投影
val list: List<*> = listOf("a", 1, true)  // 对应 Java List<?>

泛型擦除与具体化

// 普通泛型函数(类型擦除)
fun <T> checkType(obj: T): Boolean {
    return obj is String  // 警告:类型擦除
}

// 内联函数的具体化类型参数
inline fun <reified T> checkTypeReified(obj: Any): Boolean {
    return obj is T  // 可以正常工作
}

// 使用
val result1 = checkTypeReified<String>("test")  // true
val result2 = checkTypeReified<Int>("test")     // false

7. 集合与数组性能对比

// 性能测试示例
fun performanceComparison() {
    val size = 1_000_000
    
    // IntArray (基本类型数组) - 最高效
    val intArray = IntArray(size) { it }
    
    // Array<Int> (包装类型数组) - 次之
    val array = Array(size) { it }
    
    // List<Int> - 再次之
    val list = List(size) { it }
    
    // MutableList<Int> - 最慢
    val mutableList = MutableList(size) { it }
}

8. 自定义类型映射

使用类型别名

// 为复杂类型创建别名
typealias UserId = String
typealias UserMap = Map<UserId, User>
typealias Callback = (Result) -> Unit

// 使用
fun processUser(users: UserMap, callback: Callback) {
    // ...
}

自定义值类(内联类)

// 创建类型安全的值类(无运行时开销)
@JvmInline
value class Email(val value: String)

@JvmInline
value class UserId(val value: Long)

// 使用
fun sendEmail(to: Email) {
    // 编译时类型安全,运行时无额外开销
}

// 不会混淆不同类型
val email = Email("test@example.com")
val userId = UserId(123L)
// sendEmail(userId) // 编译错误:类型不匹配

9. 与 Java 集合的互操作

转换方法

// Java 集合转 Kotlin 集合
val javaList: java.util.ArrayList<String> = java.util.ArrayList()
val kotlinList: List<String> = javaList.toList()
val mutableKotlinList: MutableList<String> = javaList.toMutableList()

// Kotlin 集合转 Java 集合
val kotlinMutableList = mutableListOf("a", "b")
val javaList2: java.util.List<String> = kotlinMutableList  // 直接赋值
val javaArrayList: java.util.ArrayList<String> = ArrayList(kotlinMutableList)

平台集合的注意事项

// Java 方法返回的可变集合
fun getJavaMutableList(): java.util.List<String> {
    return java.util.ArrayList(listOf("a", "b"))
}

// 在 Kotlin 中使用
val list = getJavaMutableList()
list.add("c")  // 可以,但可能破坏不可变性假设

// 更好的做法:防御性拷贝
val safeList = getJavaMutableList().toList()  // 创建不可变副本

10. 实际应用示例

示例1:处理混合类型数据

fun processMixedData(data: Any) {
    when (data) {
        is Int -> println("整数: $data")
        is String -> println("字符串: ${data.length}")
        is IntArray -> println("整数数组: ${data.sum()}")
        is List<*> -> println("列表大小: ${data.size}")
        else -> println("未知类型")
    }
}

示例2:类型安全的 API 设计

// 使用值类创建类型安全的API
@JvmInline value class Meter(val value: Double)
@JvmInline value class Kilometer(val value: Double)

fun Meter.toKilometer(): Kilometer = Kilometer(value / 1000)
fun Kilometer.toMeter(): Meter = Meter(value * 1000)

// 使用 - 类型安全
val distanceInMeters = Meter(1000.0)
val distanceInKm = distanceInMeters.toKilometer()
// val error = distanceInMeters + distanceInKm // 编译错误

示例3:处理 JSON 映射

// 使用类型映射处理 JSON
data class User(
    val id: Long,
    val name: String,
    val email: String,
    val tags: List<String>
)

fun parseUser(json: String): User {
    // 假设使用 Gson 或 Jackson
    val map = mapOf<String, Any>(
        "id" to 123L,
        "name" to "John",
        "email" to "john@example.com",
        "tags" to listOf("admin", "user")
    )
    
    return User(
        id = map["id"] as Long,
        name = map["name"] as String,
        email = map["email"] as String,
        tags = map["tags"] as List<String>
    )
}

最佳实践

  1. 优先使用 Kotlin 集合:除非需要与 Java 代码深度互操作
  2. 明确处理可空性:与 Java 互操作时使用适当的注解
  3. 使用值类:创建类型安全的领域模型
  4. 注意平台类型:避免在 Kotlin 中传播平台类型
  5. 性能考虑:大数据集使用基本类型数组
  6. 类型安全:利用 Kotlin 的类型系统防止运行时错误

Kotlin 的类型映射系统在保证类型安全的同时,提供了与 Java 无缝互操作的能力。合理利用这些特性可以编写更安全、更高效的代码。