Kotlin是一种编程语言,被Android开发人员广泛使用。本主题是Kotlin速成班,可帮助您快速入门和运行。
变量声明
Kotlin使用两个不同的关键字来声明变量:val和var。
使用val了其值永远不会改变的变量。您不能将值重新分配给使用声明的变量val。
使用var了其值可以改变的变量。
在下面的示例中,count是类型为变量的变量,Int其初始值为10:
var count: Int = 10
Int是代表整数的类型,整数是可以在Kotlin中表示的许多数值类型之一。类似其他语言,你也可以使用 Byte,Short,Long,Float,并Double根据您的数字数据。
该var关键字,您可以重新分配值count需要。例如,您可以将countfrom 的值更改10为15:
var count: Int = 10
count = 15
但是,某些值不打算更改。考虑一个String称为 languageName。如果要确保languageName始终保持“ Kotlin”的值,则可以languageName使用val关键字进行声明:
val languageName: String = "Kotlin"
这些关键字使您可以明确说明可以更改的内容。根据需要使用它们以发挥自己的优势。如果必须重新分配变量引用,则将其声明为var。否则,请使用val。
类型推断
继续前面的示例,当您将初始值分配给时 languageName,Kotlin编译器可以根据分配值的类型来推断类型。
由于"Kotlin"值是String,因此编译器推断这 languageName也是一个 String。请注意,Kotlin是一种静态类型的 语言。这意味着该类型在编译时已解析,并且永不更改。
在下面的示例中,languageName推断为String,因此您不能调用不属于String该类的任何函数:
val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()
// Fails to compile
languageName.inc()
toUpperCase()是只能在类型为的变量上调用的函数 String。由于Kotlin编译器将其推断languageName为a String,因此您可以安全地调用toUpperCase()。inc()但是,它是一个Int运算符,因此不能在上调用String。Kotlin的类型推断方法为您提供了简洁性和类型安全性。
空安全
在某些语言中,可以在不提供初始显式值的情况下声明引用类型变量。在这些情况下,变量通常包含空值。默认情况下,Kotlin变量不能包含空值。这意味着以下代码段无效:
// Fails to compile
val languageName: String = null
要使变量具有空值,它必须是可空类型。可以通过在变量的类型后缀来将变量指定为可空值?,如以下示例所示:
// Fails to compile
val languageName: String? = null
随着String?类型,你可以指定无论是String价值还是null到 languageName。
您必须谨慎处理可为空的变量,否则可能会造成可怕的后果 NullPointerException。例如,在Java中,如果尝试对空值调用方法,则程序将崩溃。
Kotlin提供了许多机制来安全处理可为空的变量。有关更多信息,请参阅 Android中的常见Kotlin模式:Nullability。
有条件的
Kotlin具有几种用于实现条件逻辑的机制。其中最常见的是if-else语句。如果在if关键字旁边用括号括起来的表达式的计算结果为true,则执行该分支内的代码(即紧接在花括号中的紧跟其后的代码)。否则,将else执行分支内的代码。
if (count == 42) {
println("I have the answer.")
} else {
println("The answer eludes me.")
}
您可以使用表示多个条件else if。这使您可以在单个条件语句中表示更精细,更复杂的逻辑,如以下示例所示:
if (count == 42) {
println("I have the answer.")
} else if (count > 35) {
println("The answer is close.")
} else {
println("The answer eludes me.")
}
条件语句对于表示状态逻辑很有用,但是您可能会发现编写它们时会重复自己。在上面的示例中,您只需String在每个分支中打印一个。为了避免这种重复,Kotlin提供了 条件表达式。最后一个示例可以重写如下:
val answerString: String = if (count == 42) {
"I have the answer."
} else if (count > 35) {
"The answer is close."
} else {
"The answer eludes me."
}
println(answerString)
隐式地,每个条件分支在其最后一行返回表达式的结果,因此您不需要使用return关键字。因为所有三个分支的结果都是type String,所以if-else表达式的结果也是type String。在此示例中,answerString从if-else表达式的结果中分配了一个初始值。类型推断可用于省略的显式类型声明answerString,但为清楚起见通常将其包括在内是一个好主意。
注意:Kotlin不包括传统的 三元运算符,而是倾向于使用条件表达式。
随着条件语句的复杂性增加,您可以考虑将if-else表达式替换为when表达式,如以下示例所示:
val answerString = when {
count == 42 -> "I have the answer."
count > 35 -> "The answer is close."
else -> "The answer eludes me."
}
println(answerString)
when表达式中的每个分支均由条件,箭头(->)和结果表示。如果箭头左侧的条件求值为true,则返回右侧表达式的结果。请注意,执行不会从一个分支到下一个分支。when表达式示例中的代码在功能上与先前示例中的代码等效,但是可以说更易于阅读。
Kotlin的条件突出了其更强大的功能之一,即 智能铸造。您可以使用条件语句来检查变量是否包含对空值的引用,而不是使用安全调用运算符或非空断言运算符来处理可空值,如以下示例所示:
val languageName: String? = null
if (languageName != null) {
// No need to write languageName?.toUpperCase()
println(languageName.toUpperCase())
}
在条件分支内,languageName可以视为不可为空。Kotlin足够聪明,可以认识到执行分支的条件是languageName不包含null值,因此您不必languageName在该分支内将其 视为可为空。这种智能转换适用于null检查, 类型检查或任何满足合同的条件 。
功能
您可以将一个或多个表达式分组为一个函数。您可以将表达式包装在一个函数中,然后调用该函数,而不是每次需要结果时都重复相同的一系列表达式。
要声明一个函数,请使用fun关键字,后跟函数名称。接下来,定义函数采用的输入类型(如果有),并声明其返回的输出类型。函数的主体是定义调用函数时要调用的表达式的地方。
在前面的示例的基础上,以下是完整的Kotlin函数:
fun generateAnswerString(): String {
val answerString = if (count == 42) {
"I have the answer."
} else {
"The answer eludes me"
}
return answerString
}
上面示例中的函数具有名称generateAnswerString。它不需要任何输入。输出类型为的结果String。要调用函数,请使用其名称,后跟调用运算符(())。在下面的示例中,answerString变量使用的结果初始化 generateAnswerString()。
val answerString = generateAnswerString()
函数可以将参数作为输入,如以下示例所示:
fun generateAnswerString(countThreshold: Int): String {
val answerString = if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
return answerString
}
声明函数时,可以指定任意数量的参数及其类型。在上面的示例中,generateAnswerString()采用一个名为countThresholdtype的参数 Int。在函数内,您可以使用参数名称来引用该参数。
调用此函数时,必须在函数调用的括号内包含一个参数:
val answerString = generateAnswerString(42)
简化函数声明
generateAnswerString()是一个相当简单的功能。该函数声明一个变量,然后立即返回。从函数返回单个表达式的结果时,可以通过直接返回函数中包含的if-else表达式的结果来跳过声明局部变量的步骤,如以下示例所示:
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
您还可以使用赋值运算符替换return关键字:
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
匿名功能
并非每个函数都需要一个名称。某些功能可以通过其输入和输出来直接识别。这些功能称为匿名功能。您可以保留对匿名函数的引用,以后使用该引用来调用匿名函数。您还可以像其他引用类型一样在应用程序中传递引用。
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
val stringLength: Int = stringLengthFunc("Android")
高阶函数
一个函数可以将另一个函数作为参数。将其他函数用作参数的函数称为高阶函数。该模式对于组件之间的通信很有用,就像您在Java中使用回调接口一样。
这是一个高阶函数的示例:
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
该stringMapper()函数String与一个函数一起使用,该函数Int从String传递给它的a 派生一个值。
您可以stringMapper()通过传递String和来满足其他输入参数的函数进行调用,即,将a String作为输入并输出an 的函数Int,如以下示例所示:
stringMapper("Android", { input ->
input.length
})
如果匿名函数是函数上定义的最后一个参数,则可以将其传递到用于调用该函数的括号之外,如以下示例所示:
stringMapper("Android") { input ->
input.length
}
在整个Kotlin标准库中都可以找到匿名函数。有关更多信息,请参见 高阶函数和Lambda。
类
到目前为止提到的所有类型都内置在Kotlin编程语言中。如果要添加自己的自定义类型,则可以使用class关键字定义一个类,如以下示例所示
class Car
属性
类使用属性表示状态。一个 属性是类级的变量,其可以包括getter,setter,和一个backing字段。由于汽车需要车轮来驱动,因此您可以将Wheel对象列表添加为的属性Car,如以下示例所示:
class Car {
val wheels = listOf<Wheel>()
}
请注意,它wheels是一个public val,表示wheels可以从Car类外部访问,并且不能重新分配。如果要获取的实例Car,则必须首先调用其构造函数。从那里,您可以访问其任何可访问的属性。
val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car
如果要自定义轮子,则可以定义一个自定义构造函数,该构造函数指定如何初始化类属性:
class Car(val wheels: List<Wheel>)
在上面的示例中,类构造函数将a List作为构造函数参数,并使用该参数初始化其wheels 属性。
类函数和封装
类使用函数对行为进行建模。函数可以修改状态,从而帮助您仅公开希望公开的数据。此访问控制是称为封装的更大的面向对象概念的一部分。
在下面的示例中,该doorLock属性对Car类外部的任何内容保持私有。要解锁汽车,必须调用unlockDoor() 传递有效键的函数,如以下示例所示:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
如果要自定义如何引用属性,则可以提供自定义的getter和setter。例如,如果您想在限制访问属性设置器的同时公开属性的getter,则可以将该属性指定为 private:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
val gallonsOfFuelInTank: Int = 15
private set
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
通过属性和函数的组合,可以创建对所有类型的对象建模的类。
互通性
Kotlin最重要的功能之一是它与Java的流畅互操作性。由于Kotlin代码可以编译为JVM字节码,因此您的Kotlin代码可以直接调用Java代码,反之亦然。这意味着您可以直接从Kotlin利用现有的Java库。此外,大多数Android API都是用Java编写的,您可以直接从Kotlin对其进行调用。
Kotlin是一种灵活,实用的语言,具有越来越多的支持和动力。如果您还没有尝试,我们鼓励您尝试一下。接下来,请查看Kotlin官方文档 以及有关如何在Android应用中应用常见Kotlin模式的指南 。