MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kotlin变量类型与数据表示

2024-11-094.9k 阅读

Kotlin 变量类型基础

变量声明基础

在 Kotlin 中,变量声明主要通过 varval 关键字。var 用于声明可变变量,意味着其值在程序执行过程中可以改变;而 val 用于声明只读变量,一旦初始化后,其值就不能再改变。例如:

var mutableVariable: Int = 10
val immutableVariable: String = "Hello, Kotlin!"

这里 mutableVariable 是一个可变的整数变量,而 immutableVariable 是一个不可变的字符串变量。

类型推断

Kotlin 具有强大的类型推断机制。在变量声明时,如果提供了初始值,Kotlin 编译器可以自动推断变量的类型。例如:

var inferredVariable = 20 // Kotlin 推断 inferredVariable 为 Int 类型
val inferredString = "Inferred String" // Kotlin 推断 inferredString 为 String 类型

这大大减少了代码中的冗余类型声明,提高了代码的简洁性。不过,在某些情况下,显式声明类型可以提高代码的可读性,尤其是在复杂的表达式中。

基本数据类型

数值类型

  1. 整数类型 Kotlin 提供了几种整数类型,包括 Byte(8 位)、Short(16 位)、Int(32 位)和 Long(64 位)。例如:
val byteValue: Byte = 10
val shortValue: Short = 1000
val intValue: Int = 100000
val longValue: Long = 1000000000000L

这里要注意,对于 Long 类型,需要在数值后面加上 L 后缀。不同的整数类型适用于不同的场景,比如 Byte 适用于节省内存空间的场景,而 Long 适用于处理较大数值的情况。 2. 浮点类型 Kotlin 支持 Float(32 位)和 Double(64 位)两种浮点类型。例如:

val floatValue: Float = 3.14f
val doubleValue: Double = 3.141592653589793

Float 类型需要在数值后面加上 f 后缀。浮点类型用于表示带有小数部分的数值,但要注意浮点数在计算机中的表示是近似的,可能会导致精度问题。例如:

val result1 = 0.1 + 0.2
println(result1) // 输出 0.30000000000000004

这是因为 0.1 和 0.2 在二进制中是无限循环小数,无法精确表示,所以相加的结果会有微小的偏差。

字符类型

Kotlin 的字符类型是 Char,用于表示单个字符。字符用单引号括起来,例如:

val charValue: Char = 'A'

字符类型可以参与一些特定的操作,比如字符比较:

val char1: Char = 'A'
val char2: Char = 'B'
println(char1 < char2) // 输出 true

这里字符比较是基于它们的 Unicode 码点进行的。

布尔类型

布尔类型 Boolean 只有两个值:truefalse。它主要用于条件判断和逻辑运算。例如:

val isTrue: Boolean = true
val isFalse: Boolean = false
val result = isTrue && isFalse // 逻辑与运算,结果为 false

布尔类型在控制流语句(如 if - elsewhile 等)中起着关键作用。

引用类型

字符串类型

  1. 字符串基础 Kotlin 的字符串类型是 String,用于表示字符序列。字符串可以用双引号括起来,例如:
val simpleString: String = "Hello, World!"

字符串支持很多操作,比如获取长度:

val length = simpleString.length
println(length) // 输出 13
  1. 字符串模板 字符串模板是 Kotlin 中一个非常实用的特性。它允许在字符串中嵌入变量或表达式。例如:
val name = "Kotlin"
val greeting = "Hello, $name!"
println(greeting) // 输出 Hello, Kotlin!

还可以在字符串模板中嵌入更复杂的表达式:

val num1 = 10
val num2 = 20
val resultString = "The sum of $num1 and $num2 is ${num1 + num2}"
println(resultString) // 输出 The sum of 10 and 20 is 30
  1. 多行字符串 Kotlin 支持多行字符串,通过三个双引号(""")来定义。例如:
val multiLineString = """
    This is a
    multi - line
    string.
""".trimIndent()
println(multiLineString)

这里 trimIndent() 方法用于去除每行开头的缩进,使字符串更加美观。

数组类型

  1. 数组声明与初始化 Kotlin 中的数组由 Array 类表示。可以使用 arrayOf() 函数来创建数组,例如:
val intArray = arrayOf(1, 2, 3, 4, 5)
val stringArray = arrayOf("apple", "banana", "cherry")

也可以创建特定类型的空数组,然后再填充元素:

val emptyIntArray = IntArray(5)
for (i in 0 until emptyIntArray.size) {
    emptyIntArray[i] = i * 2
}
  1. 访问数组元素 可以通过索引来访问数组元素,索引从 0 开始。例如:
println(intArray[2]) // 输出 3
  1. 数组操作 Kotlin 提供了丰富的数组操作函数,比如 sum() 用于计算数组元素的总和:
println(intArray.sum()) // 输出 15

还有 filter() 用于过滤数组元素:

val filteredArray = intArray.filter { it % 2 == 0 }
println(filteredArray) // 输出 [2, 4]

集合类型

  1. 列表(List) 列表是一种有序的集合,元素可以重复。Kotlin 有可变列表 MutableList 和不可变列表 List。例如,创建一个不可变列表:
val immutableList: List<Int> = listOf(1, 2, 3, 4)

创建一个可变列表:

val mutableList: MutableList<String> = mutableListOf("one", "two", "three")
mutableList.add("four")
  1. 集合(Set) 集合是一种无序且元素不重复的集合。Kotlin 有可变集合 MutableSet 和不可变集合 Set。例如,创建一个不可变集合:
val immutableSet: Set<Int> = setOf(1, 2, 3, 3)
println(immutableSet) // 输出 [1, 2, 3],重复元素被去除

创建一个可变集合:

val mutableSet: MutableSet<String> = mutableSetOf("apple", "banana")
mutableSet.add("cherry")
  1. 映射(Map) 映射是一种键值对的集合。Kotlin 有可变映射 MutableMap 和不可变映射 Map。例如,创建一个不可变映射:
val immutableMap: Map<String, Int> = mapOf("one" to 1, "two" to 2)

创建一个可变映射:

val mutableMap: MutableMap<String, String> = mutableMapOf("name" to "Kotlin")
mutableMap.put("language", "programming")

可空类型

可空类型声明

在 Kotlin 中,默认情况下变量是不可为空的。但有时需要处理可能为空的值,这时就用到可空类型。可空类型通过在类型后面加上 ? 来声明。例如:

var nullableString: String? = "Nullable String"
nullableString = null

这里 nullableString 被声明为可空字符串类型,它可以赋值为 null

空安全操作

  1. 安全调用操作符(?.) 安全调用操作符用于在调用可能为空的对象的方法或属性时避免空指针异常。例如:
val length = nullableString?.length
println(length) // 如果 nullableString 为 null,输出 null;否则输出字符串长度
  1. Elvis 操作符(?:) Elvis 操作符用于在对象可能为空时提供一个默认值。例如:
val result = nullableString?.length?: 0
println(result) // 如果 nullableString 为 null,输出 0;否则输出字符串长度
  1. 非空断言操作符(!!) 非空断言操作符用于明确告诉编译器某个可空对象不会为空。但如果对象实际上为空,会抛出 NullPointerException。例如:
val nonNullLength = nullableString!!.length
println(nonNullLength) // 如果 nullableString 为 null,抛出 NullPointerException

使用 !! 要非常谨慎,尽量在确保对象不为空的情况下使用。

类型转换与类型检查

显式类型转换

  1. 数值类型转换 在 Kotlin 中,数值类型之间的转换需要显式进行。例如,将 Int 转换为 Long
val intValue: Int = 10
val longValue: Long = intValue.toLong()

不同数值类型有各自的转换方法,如 toByte()toShort()toFloat()toDouble() 等。 2. 其他类型转换 字符串转换为数值类型可以使用 toInt()toDouble() 等方法,但要注意字符串格式必须正确,否则会抛出异常。例如:

val stringNumber = "10"
val intNumber = stringNumber.toInt()

如果字符串格式不正确,如 val wrongString = "abc",调用 wrongString.toInt() 会抛出 NumberFormatException

类型检查

  1. is 操作符 is 操作符用于检查对象是否是某个类型。例如:
val obj: Any = "Hello"
if (obj is String) {
    println("It's a string")
}
  1. as 操作符 as 操作符用于类型强制转换。例如:
val obj: Any = 10
val intValue = obj as Int

但如果对象实际类型与转换类型不匹配,会抛出 ClassCastException。为了避免这种情况,可以结合 is 操作符使用:

val obj: Any = "not an int"
if (obj is Int) {
    val intValue = obj as Int
} else {
    println("Object is not an int")
}

自定义类型

类的定义

在 Kotlin 中,可以通过 class 关键字定义类。类可以包含属性和方法。例如:

class Person {
    var name: String = ""
    var age: Int = 0

    fun introduce() {
        println("My name is $name and I'm $age years old.")
    }
}

这里定义了一个 Person 类,有 nameage 两个属性,以及 introduce() 方法。

对象实例化

可以通过 new 关键字(在 Kotlin 中可以省略)来创建类的实例。例如:

val person = Person()
person.name = "John"
person.age = 30
person.introduce()

数据类

数据类是 Kotlin 中一种特殊的类,主要用于存储数据。它会自动生成一些有用的方法,如 equals()hashCode()toString() 等。例如:

data class Point(val x: Int, val y: Int)
val point1 = Point(10, 20)
val point2 = Point(10, 20)
println(point1 == point2) // 输出 true,因为数据类自动生成了 equals 方法

Kotlin 类型系统的高级特性

泛型类型

  1. 泛型类 泛型允许在定义类、接口或函数时使用类型参数。例如,定义一个简单的泛型类 Box
class Box<T>(val value: T) {
    fun getValue(): T {
        return value
    }
}
val intBox = Box(10)
val stringBox = Box("Hello")

这里 T 是类型参数,Box 类可以存储任何类型的值。 2. 泛型函数 也可以定义泛型函数。例如,一个交换两个值的泛型函数:

fun <T> swap(a: T, b: T): Pair<T, T> {
    return Pair(b, a)
}
val result = swap(10, 20)
println(result) // 输出 Pair(20, 10)

类型别名

类型别名允许为现有类型定义一个新的名称。例如:

typealias MyFunction = (Int, Int) -> Int
fun add(a: Int, b: Int): Int {
    return a + b
}
val myAdd: MyFunction = ::add

这里 MyFunction 是一个函数类型的别名,代表接受两个 Int 参数并返回一个 Int 的函数。

密封类

密封类用于表示受限的类继承结构。它的所有子类必须在与密封类相同的文件中声明。例如:

sealed class Shape
class Circle(val radius: Double) : Shape()
class Rectangle(val width: Double, val height: Double) : Shape()
fun calculateArea(shape: Shape): Double {
    return when (shape) {
        is Circle -> Math.PI * shape.radius * shape.radius
        is Rectangle -> shape.width * shape.height
    }
}

密封类在 when 表达式中使用非常方便,可以确保覆盖所有可能的情况,避免遗漏。

枚举类型

枚举类型用于定义一组命名常量。例如:

enum class Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
val today = Day.MONDAY

枚举类型可以有属性和方法。例如:

enum class Weekday(val value: Int) {
    MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5);
    fun isWeekend(): Boolean {
        return this!in listOf(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY)
    }
}

通过以上对 Kotlin 变量类型与数据表示的详细介绍,我们深入了解了 Kotlin 在处理不同类型数据方面的强大功能和灵活性。从基本数据类型到复杂的自定义类型,以及各种高级特性,Kotlin 提供了丰富的工具和机制,帮助开发者编写出高效、健壮且简洁的代码。无论是初学者还是有经验的开发者,都可以从 Kotlin 强大的类型系统中受益。在实际编程中,根据具体的需求选择合适的变量类型和数据结构,是编写高质量 Kotlin 代码的关键。同时,深入理解类型转换、类型检查以及可空类型等概念,能够有效地避免运行时错误,提高程序的稳定性和可靠性。希望以上内容能为你在 Kotlin 开发中更好地运用变量类型和数据表示提供有力的帮助。