数据类型
概述
Kotlin拥有丰富的类型系统,包括基本类型、集合类型、函数类型等。本章将详细介绍Kotlin的类型系统,包括类型推断、空安全、泛型等重要概念。
基本数据类型
数字类型
kotlin
fun main() {
// 整数类型
val byte: Byte = 127 // 8位,-128到127
val short: Short = 32767 // 16位,-32768到32767
val int: Int = 2147483647 // 32位,-2^31到2^31-1
val long: Long = 9223372036854775807L // 64位,-2^63到2^63-1
// 浮点类型
val float: Float = 3.14f // 32位IEEE 754
val double: Double = 3.14159265359 // 64位IEEE 754
println("整数类型:")
println("Byte: $byte (${Byte.MIN_VALUE} to ${Byte.MAX_VALUE})")
println("Short: $short (${Short.MIN_VALUE} to ${Short.MAX_VALUE})")
println("Int: $int (${Int.MIN_VALUE} to ${Int.MAX_VALUE})")
println("Long: $long (${Long.MIN_VALUE} to ${Long.MAX_VALUE})")
println("\n浮点类型:")
println("Float: $float")
println("Double: $double")
}数字类型转换
kotlin
fun main() {
val int: Int = 42
// 显式转换(Kotlin不支持隐式转换)
val long: Long = int.toLong()
val double: Double = int.toDouble()
val float: Float = int.toFloat()
val byte: Byte = int.toByte()
println("原始值: $int")
println("转换为Long: $long")
println("转换为Double: $double")
println("转换为Float: $float")
println("转换为Byte: $byte")
// 数字运算
val a = 10
val b = 3
println("\n数字运算:")
println("$a + $b = ${a + b}")
println("$a - $b = ${a - b}")
println("$a * $b = ${a * b}")
println("$a / $b = ${a / b}") // 整数除法
println("$a % $b = ${a % b}") // 取余
println("$a / $b.0 = ${a / b.0}") // 浮点除法
}位运算
kotlin
fun main() {
val a = 0b1010 // 10 in binary
val b = 0b1100 // 12 in binary
println("a = $a (${a.toString(2)})")
println("b = $b (${b.toString(2)})")
println()
// 位运算操作
println("a shl 1 = ${a shl 1} (${(a shl 1).toString(2)})") // 左移
println("a shr 1 = ${a shr 1} (${(a shr 1).toString(2)})") // 右移
println("a ushr 1 = ${a ushr 1}") // 无符号右移
println("a and b = ${a and b} (${(a and b).toString(2)})") // 按位与
println("a or b = ${a or b} (${(a or b).toString(2)})") // 按位或
println("a xor b = ${a xor b} (${(a xor b).toString(2)})") // 按位异或
println("a.inv() = ${a.inv()} (${a.inv().toString(2)})") // 按位取反
}字符和字符串
字符类型
kotlin
fun main() {
val char: Char = 'A'
val digit: Char = '9'
val unicode: Char = '\u0041' // Unicode A
println("字符: $char")
println("数字字符: $digit")
println("Unicode字符: $unicode")
// 字符属性检查
println("\n字符属性:")
println("'$char' 是字母: ${char.isLetter()}")
println("'$digit' 是数字: ${digit.isDigit()}")
println("'$char' 是大写: ${char.isUpperCase()}")
println("'$char' 转小写: ${char.lowercaseChar()}")
// 字符转换
if (digit.isDigit()) {
val numericValue = digit.digitToInt()
println("'$digit' 的数值: $numericValue")
}
}字符串类型
kotlin
fun main() {
val str1 = "Hello, Kotlin!"
val str2 = "World"
// 字符串属性
println("字符串长度: ${str1.length}")
println("第一个字符: ${str1[0]}")
println("最后一个字符: ${str1[str1.length - 1]}")
// 字符串方法
println("\n字符串方法:")
println("大写: ${str1.uppercase()}")
println("小写: ${str1.lowercase()}")
println("包含'Kotlin': ${str1.contains("Kotlin")}")
println("以'Hello'开头: ${str1.startsWith("Hello")}")
println("以'!'结尾: ${str1.endsWith("!")}")
// 字符串操作
println("\n字符串操作:")
println("连接: ${str1 + " " + str2}")
println("替换: ${str1.replace("Kotlin", "World")}")
println("子字符串: ${str1.substring(0, 5)}")
println("分割: ${str1.split(" ")}")
// 字符串模板
val name = "Alice"
val age = 25
println("\n字符串模板:")
println("姓名: $name, 年龄: $age")
println("明年年龄: ${age + 1}")
println("姓名长度: ${name.length}")
}原始字符串和转义
kotlin
fun main() {
// 转义字符串
val escaped = "第一行\n第二行\t制表符\\"反斜杠\\""
println("转义字符串:")
println(escaped)
// 原始字符串(三重引号)
val raw = """
|这是原始字符串
|可以包含换行符
|和"引号"而无需转义
|反斜杠 \ 也是字面量
|${1 + 1} 仍然会被处理
""".trimMargin()
println("\n原始字符串:")
println(raw)
// 不处理模板的原始字符串
val rawNoTemplate = """
不处理模板: ${'$'}{1 + 1}
使用 ${'$'}{'$'} 来输出字面量 $
""".trimIndent()
println("\n不处理模板的原始字符串:")
println(rawNoTemplate)
}布尔类型
kotlin
fun main() {
val isTrue: Boolean = true
val isFalse: Boolean = false
// 布尔运算
println("布尔运算:")
println("true && false = ${true && false}") // 逻辑与
println("true || false = ${true || false}") // 逻辑或
println("!true = ${!true}") // 逻辑非
// 短路求值
fun expensiveOperation(): Boolean {
println("执行昂贵操作")
return true
}
println("\n短路求值:")
println("false && expensiveOperation() = ${false && expensiveOperation()}") // 不会执行
println("true || expensiveOperation() = ${true || expensiveOperation()}") // 不会执行
}数组
基本数组
kotlin
fun main() {
// 创建数组
val numbers = arrayOf(1, 2, 3, 4, 5)
val strings = arrayOf("apple", "banana", "cherry")
val mixed = arrayOf(1, "hello", 3.14, true) // Any类型数组
// 指定类型的数组
val integers: Array<Int> = arrayOf(1, 2, 3)
val nullableStrings: Array<String?> = arrayOfNulls(5)
// 使用构造函数创建数组
val squares = Array(5) { i -> i * i } // [0, 1, 4, 9, 16]
println("数组内容:")
println("numbers: ${numbers.contentToString()}")
println("strings: ${strings.contentToString()}")
println("squares: ${squares.contentToString()}")
// 数组访问和修改
println("\n数组操作:")
println("第一个元素: ${numbers[0]}")
println("数组长度: ${numbers.size}")
numbers[0] = 10
println("修改后: ${numbers.contentToString()}")
// 数组遍历
println("\n数组遍历:")
for (number in numbers) {
print("$number ")
}
println()
for ((index, value) in numbers.withIndex()) {
println("索引 $index: $value")
}
}原始类型数组
kotlin
fun main() {
// 原始类型数组(避免装箱开销)
val intArray = intArrayOf(1, 2, 3, 4, 5)
val doubleArray = doubleArrayOf(1.1, 2.2, 3.3)
val booleanArray = booleanArrayOf(true, false, true)
val charArray = charArrayOf('a', 'b', 'c')
println("原始类型数组:")
println("IntArray: ${intArray.contentToString()}")
println("DoubleArray: ${doubleArray.contentToString()}")
println("BooleanArray: ${booleanArray.contentToString()}")
println("CharArray: ${charArray.contentToString()}")
// 数组操作
println("\n数组操作:")
println("求和: ${intArray.sum()}")
println("平均值: ${intArray.average()}")
println("最大值: ${intArray.maxOrNull()}")
println("最小值: ${intArray.minOrNull()}")
// 数组转换
val doubled = intArray.map { it * 2 }
val filtered = intArray.filter { it > 2 }
println("翻倍: $doubled")
println("过滤 > 2: $filtered")
}集合类型
列表 (List)
kotlin
fun main() {
// 不可变列表
val readOnlyList = listOf("apple", "banana", "cherry")
val emptyList = emptyList<String>()
val listWithNulls = listOfNotNull("apple", null, "banana", null)
// 可变列表
val mutableList = mutableListOf("kotlin", "java", "python")
val arrayList = arrayListOf<String>()
println("列表操作:")
println("只读列表: $readOnlyList")
println("去除null的列表: $listWithNulls")
// 列表操作
mutableList.add("javascript")
mutableList.remove("java")
mutableList[0] = "Kotlin" // 修改元素
println("可变列表: $mutableList")
// 列表方法
println("\n列表方法:")
println("大小: ${readOnlyList.size}")
println("是否为空: ${readOnlyList.isEmpty()}")
println("包含'apple': ${readOnlyList.contains("apple")}")
println("第一个元素: ${readOnlyList.first()}")
println("最后一个元素: ${readOnlyList.last()}")
println("获取索引1: ${readOnlyList.getOrNull(1)}")
// 列表转换
val fruits = listOf("apple", "banana", "cherry")
val upperCaseFruits = fruits.map { it.uppercase() }
val longFruits = fruits.filter { it.length > 5 }
val totalLength = fruits.sumOf { it.length }
println("\n列表转换:")
println("大写: $upperCaseFruits")
println("长度>5: $longFruits")
println("总长度: $totalLength")
}集合 (Set)
kotlin
fun main() {
// 不可变集合
val readOnlySet = setOf("apple", "banana", "apple") // 重复元素会被去除
val emptySet = emptySet<String>()
// 可变集合
val mutableSet = mutableSetOf("kotlin", "java", "python")
val hashSet = hashSetOf<String>()
val linkedHashSet = linkedSetOf<String>() // 保持插入顺序
println("集合操作:")
println("只读集合: $readOnlySet") // [apple, banana]
println("集合大小: ${readOnlySet.size}")
// 集合操作
mutableSet.add("javascript")
mutableSet.add("kotlin") // 重复元素不会被添加
mutableSet.remove("java")
println("可变集合: $mutableSet")
// 集合运算
val set1 = setOf(1, 2, 3, 4)
val set2 = setOf(3, 4, 5, 6)
println("\n集合运算:")
println("set1: $set1")
println("set2: $set2")
println("并集: ${set1 union set2}")
println("交集: ${set1 intersect set2}")
println("差集: ${set1 - set2}")
// 集合检查
println("\n集合检查:")
println("set1包含2: ${2 in set1}")
println("set1包含所有[1,2]: ${set1.containsAll(listOf(1, 2))}")
}映射 (Map)
kotlin
fun main() {
// 不可变映射
val readOnlyMap = mapOf(
"name" to "Kotlin",
"version" to "1.9",
"type" to "Programming Language"
)
val emptyMap = emptyMap<String, String>()
// 可变映射
val mutableMap = mutableMapOf<String, Int>()
val hashMap = hashMapOf<String, String>()
val linkedHashMap = linkedMapOf<String, String>() // 保持插入顺序
println("映射操作:")
println("只读映射: $readOnlyMap")
// 映射操作
mutableMap["apple"] = 5
mutableMap["banana"] = 3
mutableMap["cherry"] = 8
mutableMap.put("date", 2) // 等同于 mutableMap["date"] = 2
println("可变映射: $mutableMap")
// 映射访问
println("\n映射访问:")
println("apple的数量: ${mutableMap["apple"]}")
println("grape的数量: ${mutableMap["grape"]}") // null
println("grape的数量(默认值): ${mutableMap.getOrDefault("grape", 0)}")
println("所有键: ${mutableMap.keys}")
println("所有值: ${mutableMap.values}")
// 映射遍历
println("\n映射遍历:")
for ((fruit, count) in mutableMap) {
println("$fruit: $count")
}
// 映射转换
val doubled = mutableMap.mapValues { (_, value) -> value * 2 }
val filtered = mutableMap.filter { (_, value) -> value > 3 }
println("\n映射转换:")
println("翻倍: $doubled")
println("过滤>3: $filtered")
}可空类型
可空性基础
kotlin
fun main() {
// 非空类型
var name: String = "Kotlin"
// name = null // 编译错误
// 可空类型
var nullableName: String? = "Kotlin"
nullableName = null // 允许
println("非空类型: $name")
println("可空类型: $nullableName")
// 安全调用操作符 ?.
println("安全调用长度: ${nullableName?.length}")
// Elvis操作符 ?:
val length = nullableName?.length ?: 0
println("长度(默认值): $length")
// 非空断言 !!
nullableName = "Kotlin"
println("非空断言长度: ${nullableName!!.length}") // 谨慎使用
// 安全转换 as?
val obj: Any = "Hello"
val str: String? = obj as? String
val int: Int? = obj as? Int // null,因为转换失败
println("安全转换String: $str")
println("安全转换Int: $int")
}可空性处理模式
kotlin
// 处理可空参数
fun processName(name: String?) {
// 方式1: 使用if检查
if (name != null) {
println("处理姓名: ${name.uppercase()}") // 智能转换
} else {
println("姓名为空")
}
// 方式2: 使用let
name?.let {
println("使用let处理: ${it.uppercase()}")
}
// 方式3: 使用Elvis操作符
val processedName = name?.uppercase() ?: "UNKNOWN"
println("处理后的姓名: $processedName")
}
// 返回可空值的函数
fun findUser(id: Int): User? {
return if (id > 0) User("User$id") else null
}
data class User(val name: String)
fun main() {
processName("alice")
processName(null)
val user = findUser(1)
val invalidUser = findUser(-1)
println("找到用户: ${user?.name}")
println("无效用户: ${invalidUser?.name}")
}类型检查和转换
类型检查
kotlin
fun main() {
val items = listOf("hello", 42, 3.14, true, null)
for (item in items) {
when (item) {
is String -> println("字符串: '$item', 长度: ${item.length}")
is Int -> println("整数: $item, 平方: ${item * item}")
is Double -> println("浮点数: $item, 四舍五入: ${item.toInt()}")
is Boolean -> println("布尔值: $item, 取反: ${!item}")
null -> println("空值")
else -> println("未知类型: $item")
}
}
}类型转换
kotlin
fun main() {
val obj: Any = "Hello, Kotlin!"
// 不安全转换 as
try {
val str = obj as String
println("转换成功: $str")
// val int = obj as Int // 会抛出ClassCastException
} catch (e: ClassCastException) {
println("转换失败: ${e.message}")
}
// 安全转换 as?
val str: String? = obj as? String
val int: Int? = obj as? Int
println("安全转换String: $str")
println("安全转换Int: $int")
// 智能转换
if (obj is String) {
// 在这个作用域内,obj被智能转换为String
println("智能转换: ${obj.uppercase()}")
}
}泛型基础
泛型类和函数
kotlin
// 泛型类
class Box<T>(val value: T) {
fun get(): T = value
override fun toString(): String = "Box($value)"
}
// 泛型函数
fun <T> identity(value: T): T = value
fun <T> swap(pair: Pair<T, T>): Pair<T, T> = Pair(pair.second, pair.first)
// 多个类型参数
fun <K, V> createMap(key: K, value: V): Map<K, V> = mapOf(key to value)
fun main() {
// 使用泛型类
val stringBox = Box("Hello")
val intBox = Box(42)
println("字符串盒子: $stringBox")
println("整数盒子: $intBox")
// 使用泛型函数
val str = identity("Kotlin")
val num = identity(100)
println("Identity字符串: $str")
println("Identity数字: $num")
// 交换对
val originalPair = Pair("first", "second")
val swappedPair = swap(originalPair)
println("原始对: $originalPair")
println("交换后: $swappedPair")
// 创建映射
val map = createMap("language", "Kotlin")
println("创建的映射: $map")
}类型约束
kotlin
// 上界约束
fun <T : Number> sum(a: T, b: T): Double {
return a.toDouble() + b.toDouble()
}
// 多个约束
interface Printable {
fun print()
}
class Document : Printable {
override fun print() = println("打印文档")
}
fun <T> process(item: T) where T : Printable, T : Comparable<T> {
item.print()
// 可以使用Printable和Comparable的方法
}
fun main() {
// 使用约束的泛型函数
val intSum = sum(10, 20)
val doubleSum = sum(3.14, 2.86)
println("整数求和: $intSum")
println("浮点数求和: $doubleSum")
// sum("hello", "world") // 编译错误:String不是Number的子类型
}类型别名
kotlin
// 为复杂类型创建别名
typealias UserMap = Map<String, User>
typealias StringProcessor = (String) -> String
typealias EventHandler<T> = (T) -> Unit
// 为泛型类创建别名
typealias StringBox = Box<String>
data class User(val name: String, val email: String)
fun main() {
// 使用类型别名
val users: UserMap = mapOf(
"1" to User("Alice", "alice@example.com"),
"2" to User("Bob", "bob@example.com")
)
val processor: StringProcessor = { it.uppercase() }
val eventHandler: EventHandler<String> = { println("事件: $it") }
println("用户映射: $users")
println("处理结果: ${processor("hello")}")
eventHandler("按钮点击")
// 使用泛型类型别名
val stringBox: StringBox = Box("Hello")
println("字符串盒子: $stringBox")
}最佳实践
1. 空安全
kotlin
// 好的做法:使用安全调用和Elvis操作符
fun processUser(user: User?) {
val name = user?.name ?: "Unknown"
val email = user?.email?.lowercase() ?: "no-email"
println("用户: $name, 邮箱: $email")
}
// 避免过度使用非空断言
fun badExample(user: User?) {
// 不好:过度使用!!
// println("用户: ${user!!.name}, 邮箱: ${user!!.email}")
}2. 集合选择
kotlin
// 根据需求选择合适的集合类型
fun main() {
// 需要保持顺序且允许重复:List
val orderItems = listOf("item1", "item2", "item1")
// 需要唯一性:Set
val uniqueIds = setOf("id1", "id2", "id3")
// 需要键值映射:Map
val userPreferences = mapOf("theme" to "dark", "language" to "en")
// 需要频繁修改:使用可变版本
val mutableItems = mutableListOf<String>()
}3. 泛型使用
kotlin
// 使用泛型提高代码复用性
class Repository<T> {
private val items = mutableListOf<T>()
fun add(item: T) = items.add(item)
fun getAll(): List<T> = items.toList()
fun find(predicate: (T) -> Boolean): T? = items.find(predicate)
}
// 使用类型约束确保类型安全
fun <T : Comparable<T>> findMax(items: List<T>): T? {
return items.maxOrNull()
}下一步
了解了Kotlin的数据类型系统后,让我们学习变量和常量的声明与使用。
下一章: 变量和常量
练习题
- 创建一个程序展示所有基本数据类型的使用和转换
- 实现一个安全的除法函数,处理除零和空值情况
- 设计一个泛型的缓存类,支持不同类型的数据存储
- 编写函数来演示集合的各种操作(过滤、映射、聚合等)
- 创建一个类型安全的配置管理器,使用类型别名和泛型