Kotlin 初学者教程(示例)

什么是 Kotlin?

Kotlin 是一种开源静态类型编程语言,运行于 Java 虚拟机(JVM)。它将面向对象编程(OOP)和函数式编程结合在不受限制、独立且独特的平台上。它还允许通过微型代码将功能结合起来。Kotlin 是一种由 JetBrains 设计的通用编程语言。

Kotlin 的历史

以下是 Kotlin 历史上的重要里程碑:

创建
2016 Kotlin v1.0 发布
2017 谷歌宣布在 Android 上优先支持 Kotlin
2018 Kotlin v1.2 增加了在 JVM 和 Java脚本
2019 Google 宣布 Kotlin 为其首选编程语言 Android 应用程序开发人员
2021 20年2021月1.5.31日,Kotlin vXNUMX发布。

使用 Kotlin 的原因

以下是 Kotlin 被广泛使用的一些重要原因:

  • Kotlin 是一种静态类型语言,非常易于阅读和编写。
  • Kotlin 程序不需要在其程序中使用分号。这使得代码更简单且更易读。
  • 这种语言允许交换和使用来自 Java 以各种方式。此外, Java 和Kotlin代码可以在同一个项目中共存。
  • Kotlin 的类型系统旨在从代码中消除 NullPointerException。
  • 使用 Kotlin 编写新代码所需的时间更少。部署 Kotlin 代码并大规模维护它甚至更加容易。

科特林的特点

以下是 Kotlin 的一些特性,它们将帮助你确定该编程语言的进步路径。

修剪编码:

Kotlin 是一种基于 OOP 的编程语言,其中代码行可以减少多达 40%,这使得 Kotlin 成为软件或 Web 开发的理想选择。

开源:

科特林用于 Android 利用JVM并结合OOPs和面向函数编程的特点。

快速编译:

使用Kotlin时代码编译很容易,从而为Android开发带来更好的性能,并且还会解释在整个代码中可以使用哪种类型的数据函数。

扩展功能:

Kotlin 可以支持各种扩展功能,而无需对代码进行任何更改。它有助于使现有代码对开发人员更有吸引力、更出色。

对于实施例:

Fun String.removeFirstLastChar():
String = this.substring(1, this.length -1)

此代码将有助于修剪字符串的第一个和最后一个字符,我们可以这样应用它:

Val string1 = "Today is cloudy."
Val string2 = string1.removeFirstLastChar()

空安全:

在 Kotlin 中,系统区分空引用和非空引用,如下面的 Kotlin 示例所示。

例如,String 变量不能为空:

Var string1: String = "Today is Sunday"
String1 = null  // compilation error
To permit null, we can adjoin the nullable variable :
Var string2: String? = "Today is Sunday"
String2 = null
print(string2)

互操作性:

Kotlin 代码可用于 Java及 Java 代码可以与 Kotlin 一起使用。因此,如果您了解 面向对象 编程,很容易切换到 Kotlin 的开发。另外,如果有些应用程序是用 Java,那么它们就可以与 Kotlin 的环境一起使用了。

强大的工具:

喜欢 Java,Kotlin 代码也可以使用 IDE 或使用命令行界面编写。使用 IDE 很容易,语法错误也大大减少。同时,当你使用命令行界面时,代码必须先编译。

智能演员:

智能转换基本上有助于降低应用程序成本并提高其速度或性能。它使用类型转换或不可变值来管理代码的效率。

例如,如果识别了字符串,则可以借助 Smart Cast 函数找到它的长度和数量:

Val string1: Any = "Today is Monday"
when(string1)
{
is String  -> string1.length
Is Int -> string1.inc()
}

采用成本低:

Kotlin 之所以受到企业的青睐,是因为其采用成本低。最重要的是,开发人员很容易学习它,尤其是有编程背景的开发人员。

Kotlin 环境设置

以下步骤可帮助您通过安装 Kotlin 来设置工作环境。

步骤 1) 安装 Java

正如我们之前讨论过的,Kotlin 基于 Java,所以你必须安装 Java 计划采用 Kotlin 时,请首先参阅我们的 Java 安装教程.

步骤 2) 安装 Java 集成开发环境

幸运的是,有多个 Java 集成开发环境 可供选择。我们在这里提供了下载链接,以方便您使用。

在本 Kotlin 教程中,我们将使用 Eclipse.

步骤 3)安装 Kotlin

在以下位置安装 Kotlin Eclipse,转到 Eclipse 并单击 Eclipse 市场选择。

Kotlin 环境设置

现在,在搜索框中输入 Kotlin 关键字。单击“Go”选项列出插件。它将为您提供 Kotlin 插件的链接,您需要从给定的链接安装该插件。

Kotlin 环境设置

请重新启动 Eclipse IDE安装完成后,您可以在右上角找到快捷方式图标 Eclipse IDE。这是一种快速访问方法。

Kotlin 环境设置

另一种访问 Kotlin 的方法 Eclipse IDE 是,转到 Windows,Perspectives,打开 Perspectives,然后选择 Others 选项。在这里,您可以检查稍后安装的插件列表,如下所示。

Kotlin 环境设置

一旦您验证了 Kotlin 安装,让我们在下一步中创建第一个 Kotlin 程序。

步骤 4)第一个 Kotlin 程序

从您的第一个 Kotlin 项目开始。从文件菜单中,选择新建选项,然后选择其他并从列表中开始新的 Kotlin 项目。

Kotlin 环境设置

现在,您必须为项目定义一个名称,然后就可以使用 Kotlin 了。

Kotlin 环境设置

通过这些简单的步骤,可以轻松下载 Eclipse 并在您的系统上安装 Kotlin 并立即编写您的第一个 Kotlin 程序。

ArchiKotlin 的架构

良好的架构对于应用程序扩展其功能并满足最终用户群的期望非常重要。 Kotlin 拥有自己独特的架构来分配内存并为开发人员和最终用户获得高质量的结果。

Kotlin 的协程和类以这样一种方式构建核心,以减少样板代码、增强性能并提高效率。在各种情况下,kotlin 编译器可能会做出不同的反应,尤其是在指定各种语言时。

ArchiKotlin 的架构
ArchiKotlin 的架构

在架构图中,可以清楚地看到代码执行分为三个简单的步骤。

  1. 第一步,将“.kt”或kotlin文件添加到编译器。
  2. 第二步,Kotlin编译器将代码转换成字节码。
  3. 第三步,将字节码放入 Java 虚拟机 并由JVM执行。

当多个字节编码文件在 JVM 上运行时,它们会激发它们之间的相互通信,这就是 Kotlin 中称为互操作性的功能诞生的原因

Kotlin 的演变 Java当 Kotlin 目标为 Java脚本。

当。。。的时候 Java选择脚本的目标后,任何与 Kotlin 一起运行的库中的 Kotlin 代码都会溢出 Java脚本。然而, Java 不包括开发工具包(JDK)或任何使用的 Java 库。

此类操作不会考虑非 Kotlin 文件。虽然定位 Java脚本 .kt 文件由 Kotlin 编译器转换为 ES5.1,以生成一致的代码 Java脚本。Kotlin 编译器致力于实现最佳大小的输出、与现有模块的互操作性、与标准库相同的功能以及输出 Java脚本可读。

从讨论中可以清楚地看出,Kotlin 编译器可以创建更高效​​、更强大、更独立的代码,从而进一步产生高性能的软件产品。

Kotlin 变量

变量用于存储程序中要操作和引用的数据。它本质上是存储数据的单位,并对其进行标记以等待说明性的别名,以便程序易于阅读和理解。换句话说,我们可以说变量是收集信息的容器。

在 Kotlin 中,所有变量都应声明。但是,如果未声明任何变量,则会出现语法错误。此外,变量的声明决定了我们允许存储在变量中的数据类型。在 Kotlin 中,可以使用 val 和 var 关键字定义变量。以下是在 Kotlin 中声明变量的语法:

Var day = "Monday"
Var number = 3

这里我们声明了局部变量 day,其值为“Monday' 其类型为 String,另一个局部变量号的值为 3,其类型为 Int,因为这里的文字类型为整数 3。

局部变量通常是同时声明和初始化的。我们也可以在初始化 Kotlin 变量时执行某些操作。

我们可以对相同数据类型的变量执行操作,因为这里 num1 和 num2 都是相同的数据类型,即 Int,而 day 是字符串数据类型。因此,它会显示错误。这是另一种在 Kotlin 中定义变量的技术。

var day : String = "GURU99"
var num : Int = 100

让我们看看 var 和 val 关键字彼此有何不同。

变量:

Var 就像是任何编程语言中使用的通用变量,可以在单个程序中多次使用。此外,您可以在程序中随时更改其值。因此,它被称为可变变量。

以下是 Kotlin 中可变变量的一个示例:

var num1 = 10
Var num2 = 20
Num1 = 20
print(num1 + num2) // output : 40

这里 num1 的值 20 被 num1 的前一个值 10 覆盖。因此 num1 + num2 的输出是 40 而不是 30。

价值:

Val 就像一个常量变量,您无法在程序中更改其值,它既不能在单个程序中多次赋值,也不能在特定程序中使用一次。因此,它被称为不可变变量。

以下是 Kotlin 中不可变变量的 Kotlin 程序示例:

Val num1 = 10
Var num2 = 20

这里,num1 的值 10 不能被 num1 的新值 20 覆盖,因为它是常量 val 类型。因此,输出是 30,而不是 40。

备注:在 Kotlin 中,不可变变量比可变变量更受青睐。

Kotlin 中的数据类型

数据类型是一组可关联值,描述可对其执行的操作。与其他编程语言类似,Kotlin 也有一组预定义的数据类型,如 Int、Boolean、Char、 Double等等。

在 Kotlin 中,每种数据类型都被视为一个对象。

现在,在这个 Kotlin 基础教程中,让我们深入了解 Kotlin 中使用的预定义数据类型。

Numbers :

Kotlin 提供了一组称为数字的内置数据类型,这些数据类型又可细分为整数和浮点数 Numbers.

整数:

整数是具有四种类型的数字类别:

类型 大小(位) 最低价值 最大值
字节 8 -128 127
16 -32768 32767
诠释 32 -2,147,483,648(-231) 2,147,483,647(231 – 1)
64 -9,223,372,036,854,775,808(-263) 9,223,372,036,854,775,807(263 – 1)

浮点数 Numbers :

浮点数 Numbers 是带有一些小数的非整数。

浮点数:浮点数是 32 位单精度浮点值。

例如:var: Float x = 3.25600

Double: Double 是一个 64 位双精度浮点值。

例如:var: Double y = 2456.345587

布尔值:

Kotlin 中的布尔数据类型表示逻辑值。布尔值只有两个可能的值,即 true 或 false。

对于实施例: val 日 = true

Val day2 = false

性格

Kotlin 中的字符通过 char 关键字来表示。在 Kotlin 中,单引号表示 char 的声明。在 Java 中,char 有时用作数字,但在 Kotlin 中却无法实现。

对于实施例:

val onechar = 'x'
print(onechar) //  output : x
Val onedigit = '7'
print(onedigit) // output : 7

Kotlin 类型转换或 Kotlin 类型强制转换

类型转换是将一种类型的数据变量转换为另一种数据类型变量的过程。它也称为类型转换。

值得注意的是,在 Java,支持从较小数据类型到较大数据类型的隐式类型转换或者隐式类型强制转换。

For Example : int abc = 15;
Long bcd = abc; // compiles successfully

然而在kotlin中,根本不支持将较小的数据类型隐式转换为较大的数据类型,即int数据类型不能隐式转换为long数据类型。

For Example : var abc = 15
Val bcd : Long = abc // error

然而,在 Kotlin 中,类型转换是明确完成的。这里有辅助函数的指导,可以指导将一种数据类型变量转换为另一种数据类型变量。

有一些辅助函数专门用于将一种数据类型转换为另一种数据类型:

到Int()

toByte()

太短()

toChar()

到长()

浮动()

至Double()

For Example : var abc = 15
Val bcd : Long = abc.toLong() // compiles successfully

Kotlin Opera职权范围

Opera运算符是重要的特殊字符或符号,用于确保具有变量和值的操作数中的操作。在 Kotlin 中,有一组运算符可用于不同的操作,如算术运算、赋值运算、比较运算等。

算术 Opera器:

算术运算符用于加法、减法、乘法、除法和模数。

Opera器
+ 加法(也用于字符串连接)
减法 Opera器
* 乘法 Opera器
/ 您所属的事业部 Opera器
% 系数 Opera器

对于实施例:

var x = 10
var y = 20
var z = ( ( x + y ) * ( x + y ) ) / 2     

这里以下代码的输出是45。

竞品对比 Opera器:

比较运算符用于比较两个值、两个变量或两个数字。它与大于符号 ( > )、小于符号 ( < ) 和等于符号 ( == )、不等于符号 ( != )、大于等于符号 ( >= )、小于等于符号 ( <= ) 一起使用。它总是结果为真或假。

对于实施例:

var x = 10
Var y =20
Var z = x < y // Output : true
Var w = x > y // Output : false
Var m = x == y // Output : false

转让 Opera器:

转让 Opera用于分配算术运算值。它与 +=、-=、*=、/=、%= 等符号一起使用。

对于实施例:

var x = 10
var y = 20
var x + = y // Output : 30
Var y - = x // Output : 10
Var x * = y // Output : 200

增量和减量 Opera器:

增量和减量运算符用于增加或减少变量或数字的值。它借助 ++ 和 — 等符号使用。

增量和减量有两种类型:前增++a,后增a++,前减量-b,后减量b--。

对于实施例:

var a = 10
var b = 20
var c = a++ // Output: 11
var d = b— //Output : 19     

Kotlin 数组

数组是一组同质的数据类型,也是最基本的数据类型之一,用于将相同类型的数据存储在连续的内存位置。数组对于任何编程语言中的数据组织都很重要,这样存储在一个地方的多个数据就很容易搜索或排序。

在 Kotlin 中,数组是相同数据类型的可变协作,而不是原生数据类型。

以下是 Kotlin 中数组的某些属性

  • 数组的大小一旦声明就不能改变。
  • Kotlin 中的数组是可变的。
  • 数组存储在连续的内存位置中。
  • 可以借助索引(如 a[1]、a[2] 等)访问数组。
  • 数组的索引从零开始,即 a[0]。

在 Kotlin 中,数组可以用两种不同的方法定义

使用 arrayOf() 函数:

在 Kotlin 中,库函数的使用非常广泛。其中一个库函数是 arrayOf() 函数,它用于通过将变量的值传递给函数来定义数组。

对于实施例: 使用 arrayOf() 函数隐式声明数组类型

val x = arrayOf(1,2,3,4,5,6,7,8,9)

对于实施例: 使用 arrayOf() 函数明确声明数组的类型。

Val y = arrayOf<Int>(1,2,3,4,5,6,7,8,9)

通过使用数组构造函数:

在 Kotlin 中,有一个名为 Array 的类。因此,使用构造函数的数组来创建数组是可行的。构造函数中的数组包含两个主要参数。

Kotlin 中数组的索引是什么?

可以接受数组索引的函数返回索引的初始值。

对于实施例:

val abc = Array(7 , { i -> i*1})

这里数组的值为 7,使用 lambda 表达式来初始化元素的值。

还有各种使用特定函数访问和修改数组的方法。因此,有两个成员函数 get() 和 set(),用于访问类数组的对象。

对于实施例:

val x = arrayOf(10,20,30,40,50,60,70,80,90)
val y = x.get(0) // Output 10

这里输出为 10,因为数组索引 0 处的值为 10

注意:get() 仅接受单个值

对于实施例:

val x = arrayOf(10,20,30,40,50,60,70.80.90)
val y = x.set(2, 3) //

产量:30 40

这里,输出是 30 和 40,因为数组索引 2 处的值为 30,而索引 3 处的值为 40。

注意:set() 接受数组的多个值。

Kotlin 字符串

字符串是任何编程语言中的基本数据类型。字符串不过是字符序列。String 类表示字符串。在 Kotlin 中,所有字符串都是 String 类的对象,这意味着字符串文字是作为该类的实例实现的。

语法:

 Val myString = "Hey there!"

Kotlin 系列

集合包含若干个相同类型的对象,集合中的这些对象称为元素或项。集合可用于存储、检索、操作和聚合数据。

收藏类型:

不可变集合

此类集合支持只读功能。无法修改其元素。

方法包括:

  • 列表 – listOf() 和 listOf ()
  • 设置 – setOf()
  • 地图 – mapOf()

可变集合

它支持读写功能。

方法包括

  • 列表 – mutableListOf()、arrayListOf() 和 ArrayList
  • 集合 – mutableSetOf()、hashSetOf()
  • Map – mutableMapOf()、hashMapOf() 和 HashMap

Kotlin 函数

任何编程语言中的函数都是一组类似的语句,用于执行特定任务。函数允许将程序分解为多个小代码块。这种代码划分提高了代码的可读性、可重用性,并使程序易于管理。

Kotlin 被称为静态类型语言。这里,'fun' 关键字用于声明函数。在 Kotlin 中,有两种类型的函数,完全取决于它在标准库或用户定义中的可用性。它们是:

  • 标准库函数
  • 用户定义函数

科特林函数

Kotlin 函数

现在,让我们通过 Kotlin 代码示例详细讨论它们。

标准库函数

它们是内置库函数,可以隐式定义并可供使用。

对于示例 2:

fun main(args: Array<String>){  
var number = 9  
var result = Math.sqrt(number.toDouble())  
print("$result")  
}  

输出:

3.0

sqrt() 是库中定义的一个函数,它返回一个数字的平方根。

print() 函数将消息打印到标准输出流。

用户自定义函数

顾名思义,这些函数通常由用户创建,可用于高级编程。

这里,使用“fun”关键字声明函数。

对于示例 3:

fun functionName(){
//body of the code
}

在这里,我们调用函数来运行函数体 functionName() 内的代码

Kotlin 函数示例:

fun main(args: Array<String>){  
    sum()  
    print("code after sum")  
}  
fun sum(){  
    var num1 =8  
    var num2 = 9  
    println("sum = "+(num1+num2))  
}  

输出:

总和= 17

求和后的代码

Kotlin 中的异常处理

编程中的异常是指程序中发生的运行时问题,导致程序终止。此问题可能由于内存空间不足、数组超出范围、除以零等情况而发生。为了抑制代码执行中的此类问题,可以使用异常处理。

异常处理被定义为处理运行时问题并在执行期间维持程序流的技术。

Kotlin 使用 'throw' 表达式来抛出异常对象。这里所有异常类都是 Throwable 类的后代。

抛出 MyException(“抛出异常”)

异常处理中有四种类型的异常。它们是:

  • try – 此块包含可能产生异常的语句。它后面总是跟着 catch 或 finally 或两者。
  • catch — 它捕获从 try 块抛出的异常。
  • finally – 它总是检查异常是否被处理。
  • throw – 用于明确抛出异常。

试着抓:

在异常处理的try-catch块中,try块包含可能引发异常的代码,而catch块捕获表达式并进行处理。

try catch 块的语法:

try{    
//code with exception    
}catch(e: SomeException){  
//code handling exception  
}    

try 和 finally 块的语法

try{    
//code with exception    
}finally{  
// code finally block  
}   

最后:

在 Kolin 中,finally 块总是检查异常是否被处理,这使它成为异常处理的一个非常重要的语句。

对于示例 4:

在此代码片段中,发生了异常,并对其进行了处理。

fun main (args: Array<String>){  
    try {  	
        val data =  9/ 0  
        println(data)  
    } catch (e: ArithmeticException) {  
        println(e)  
    } finally {  
        println("finally block executes")  
    }  
    println("write next code")  
}  

输出:

java.lang.ArithmeticException: / by zero
finally block executes
write next code

扔:

Throw 块抛出显式异常。此外,它还用于抛出自定义异常。

语法:

Throw SomeException()

Throw SomeException()

示例:

fun main(args: Array<String>) {
    try{
        println("Exception is not thrown yet")
        throw Exception("Everything is not well")
        println("Exception is thrown")
    }
    catch(e: Exception){
        println(e)

    }
    finally{
        println("You can't ignore me")
    }
}

输出:

Kotlin 示例

Kotlin 空安全

支持 Kotlin 的系统类型主要区分了哪些引用可以携带可空引用,哪些不能携带可空引用。Kotlin 是一种空安全语言,旨在消除代码中的空指针异常或空引用,这被故意称为 A Bill离子美元错误。

许多人最常犯的绊脚石 编程语言 问题是,在访问空引用的成员时,会产生 NullPointerException,这可能是因为 !! 运算符或此构造函数在其他地方使用并传递到另一代码点。每次使用可空属性之前,都需要确认是否进行空检查。

在 Kotlin 中,系统区分空引用和非空引用。

例如,String 变量不能为空:

对于示例 5:

fun main(args: Array<String>){
    var x: String = "GURU99 is the only place where you will get maximum technical content!" // Not Null by default
    println("x is : $x")
    // You cannot assign null variable to not-nullable variables 
    // a=null // it will give compilation error
    var y: String? = "Thanks for visiting GURU99" 
// Nullable Variable
    println("y is : $y")
    y = null
    println("y is : $y")
}

输出:

Kotlin 空安全

Kotlin 面向对象编程

面向对象的编程方法允许通过创建对象将复杂的代码片段划分为更小的代码块。这些对象相互共享两个特性:状态和行为。

以下是我们将通过 Kotlin 代码示例讨论的一些 OOP 元素:

  • 类和对象
  • 构造函数
  • 遗产
  • 抽象类

Kotlin 面向对象编程

Kotlin 中的类

首先在创建一个对象之前,我们需要定义一个类,也就是该对象的蓝图。

语法:

class ClassName {
    // property
    // member function
    ... .. ...
}

Kotlin 中的对象

在定义类时,我们仅定义对象的规范,不分配内存或存储等其他参数。

语法:

var obj1 = ClassName()

Kotlin 中的构造函数

构造函数是一种初始化类属性的方法。它是在实例化对象时调用的成员函数。但在 Kotlin 中,它的工作方式有所不同。

Kotlin 中有两种类型的构造函数:

Kotlin 中的构造函数

Kotlin 中的构造函数

主构造函数:初始化类的优化方式

语法:

class myClass(valname: String,varid: Int) {  
    // class body  
}  

辅助构造函数:帮助添加初始化逻辑

Kotlin 继承

当子类获得父类的某些属性时,就会发生继承。当两个或多个类具有相同的属性时,允许继承。

语法:

open class ParentClass(primary_construct){
    // common code
  }class ChildClass(primary_construct): ParentClass(primary_construct_initializ){
    // ChildClass specific behaviours
  }

Kotlin 中的抽象类

抽象类是不能被实例化的类,但我们可以从它们继承子类。'abstract' 关键字用于声明抽象类。

对于示例 6:

  open class humanbeings { 
    open fun Eat() { 
        println("All Human being Eat") 
    } 
} 
abstract class Animal : humanbeings() { 
    override abstract fun Eat() 
} 
class Cat: Animal(){ 
    override fun Eat() { 
        println("Cats also loves eating") 
    } 
} 
fun main(args: Array<String>){ 
    val lt = humanbeings() 
    lt.Eat() 
    val d = Cat() 
    d.Eat() 
} 

输出:

Kotlin 中的抽象类

Kotlin 的现在与未来

现在:

  • 许多公司喜欢 Netflix、Pinterest 和 Corda 正在使用 Kotlin 创建强大的 Android 应用。
  • 在 2016 年至 2017 年短短一年的时间里,Kotlin 凭借其出色的编程功能而广受欢迎。
  • 2017 年,谷歌宣布 Kotlin 成为 Android 开发的官方编程语言。
  • 您可以快速更换 Java Kotlin 可以 100% 兼容 Java 和 Android.

未来:

总结

  • Kotlin 是 JetBrains 于 2010 年提出的一种适用于 Apache 2.0 许可下的多平台应用程序的编程语言。
  • 科特林这个名字来源于科特林岛的名字,类似地对应着 Java 以爪哇岛的名字命名。
  • 2016 年,Kotlin 第一个版本 v1.0 发布
  • Kotlin 程序不需要在其程序中使用分号。这使得代码更简单且更易读。
  • 科特林用于 Android 开发人员是一种基于 OOP 的编程语言,其中代码行可以减少多达 40%,这使得 Kotlin 成为软件或 Web 开发的理想选择。
  • 在 Kotlin 中,所有变量都应使用 var 和 val 关键字声明。
  • 与其他编程语言类似,Kotlin 也有预定义的数据类型,如 Int、Boolean、Char、 Double等等。
  • 在 Kotlin 中,有一组运算符可用于不同的运算,如算术运算、赋值运算、比较运算等。
  • 在 Kotlin 中,数组是相同数据类型的可变协作,而不是原生数据类型。
  • 在 Kotlin 中,数组使用两种方法定义——ArrayOF() 和构造函数。
  • Kotlin 是一种空安全语言,有助于从代码中删除空指针异常或空引用,这被故意称为 Bill离子美元错误。