《Kotlin从小白到大牛》第4章:Kotlin语法基础

第4章 Kotlin语法基础

本章主要为大家介绍Kotlin的一些语法,其中包括标识符、关键字、常量、变量、表达式、语句、注释和包等内容。

4.1 标识符和关键字

任何一种计算机语言都离不开标识符和关键字,因此下面将详细介绍Kotlin标识符和关键字。
4.1.1 标识符
标识符就是变量、常量、函数、属性、类、接口和扩展等由程序员指定的名字。构成标识符的字符均有一定的规范,Kotlin语言中标识符的命名规则如下:
1.区分大小写:Myname与myname是两个不同的标识符。
2.首字符,可以是下划线()或字母,但不能是数字。
3. 除首字符外其他字符,可以是下划线(
)、字母和数字。
4. 硬关键字(Hard Keywords)不能作为标识符,软关键字(Soft Keywords)、修饰符关键字(Modifier Keywords)在它们的适用场景之外可以作为标识符使用。
5. 特定标识符field和it。在Kotlin语言中有两个由编译器定义的特定标识符,它们只能在特定场景中使用有特定的作用,而在其他的场景中可以做标识符使用。
在这里插入图片描述
例如,身高、identifier、userName、User_Name、_sys_val等为合法的标识符,注意中文“身高”命名的变量是合法的;而2mail、room#、KaTeX parse error: Expected 'EOF', got '#' at position 21: …class为非法的标识符,注意#̲是非法字符;美元符()不能构成标识符,这一点与Java不同;而class是硬关键字。
在这里插入图片描述标识符示例如下:
//代码文件:chapter4/src/ch4.1.1.kt
public fun main(args: Array) {

val `class` =

“舞蹈学习班”//class是硬关键字,前后添加反引号(),可以用于声明标识符 valπ= 3.14159 //Unicode编码,可以用于声明标识符 var 您好 = "世界" //Unicode编码,可以用于声明标识符 var public = "共有的" //public是修饰符关键字,可以用于声明变量标识符 println(class`)
println(π)

val it =100                 //it是普通标识符   ①
val ary =

arrayListOf(“A”, “B”, “C”) //创建一个数组

ary.forEach {

println(it) } //it特定标识符 ②

}
其中class是关键字,事实上反引号()不是标识符的一部分,它也可以用于其他标识符,如π和π`是等价的。代码第①行和第②行都使用it标识符,代码第①行的it标识符是普通标识符,是由程序员定义的,而代码第②行的it标识符是由编译器定义的,forEach
{ println(it) }中的{println(it) }是一个Lambda表达式,it参数引用数组中元素。

4.1.2 关键字
关键字是类似于标识符的保留字符序列,由语言本身定义好的,Kotlin语言中有70多个关键字,全部是小写英文字母,以及!和?等字符构成。分为3个大类:
1.硬关键字(Hard Keywords),硬关键字如何情况下都不能作为关键字,具体包括如下关键字。
as、as?、break、class、continue、do、else、false、for、fun、if、in、!in、interface、is、!is、null、object、package、return、super、this、throw、true、try、typealias、val、var、when和while。
2.软关键字(Soft Keywords),软关键字是在它适用场景中不能作为标识符,而其他场景中可以作为标识符,具体包括如下关键字。
by、catch、constructor、delegate、dynamic、field、file、finally、get、import、init、param、property、receiver、set、setparam和where。
3.修饰符关键字(Modifier Keywords),修饰符关键字是一种特殊的软关键字,它们用来修饰函数、类、接口、参数和属性等内容,在此场景中不能作为标识符。而其他场景中可以作为标识符,具体包括如下关键字。
abstract、annotation、companion、const、crossinline、data、enum、external、final、infix、inner、internal、lateinit、noinline、open、operator、out、override、private、protected、public、reified、sealed、suspend、tailrec和vararg。

4.2 常量和变量

上一章中介绍了如何使用编写一个Kotlin小程序,其中就用到了变量。常量和变量是构成表达式的重要组成部分。

4.2.1 变量
在Kotlin中声明变量,就是在标识符的前面加上关键字var,示例代码如下:
//代码文件:chapter4/src/ch4.2.1.kt

var _Hello = “HelloWorld” //声明顶层变量 ①

public fun main(args: Array) {
_Hello = “Hello, World”
var scoreForStudent: Float = 0.0f ②
var y = 20 ③
y = true //编译错误 ④
}
代码第①行、第②行和第③行分别声明了三个变量。第①行是顶层变量。代码第②行在声明变量的同时指定数据类型是Float。代码第③行声明变量时,没有指定数据类型,Kotlin编译器会根据上下文环境自动推导出来变量的数据类型,例如变量y由于被赋值为20,20默认是Int类型,所以y变量被推导为Int类型,所以试图给y赋值true(布尔值)时,会发编译错误。

4.2.2
常量和只读变量
常量和只读变量一旦初始化后就不能再被修改。在Kotlin声明常量是在标识符的前面加上val或const val关键字,它们的区别如下。
val声明的是运行期常量,常量是在运行时初始化的。
const val声明的是编译期常量,常量是在编译时初始化,只能用于顶层常量声明或声明对象中的常量声明,而且只能是String或基本数据类型(整数、浮点等)。
在这里插入图片描述
示例代码如下:
//代码文件:chapter4/src/ch4.2.2.kt
const val MAX_COUNT = 1000 //声明顶层常量 ①

const val _Hello1 = “Hello,world” //声明顶层常量 ②
const val _Hello2 = StringBuilder(“HelloWorld”)//编译错误 ③

//声明对象
object UserDAO {
const val MAX_COUNT = 100 //声明对象中的声明常量 ④
}

public fun main(args: Array) {
_Hello1 = “Hello, World” //编译错误 ⑤
val scoreForStudent: Float = 0.0f ⑥
val y = 20 ⑦
y = 30 //编译错误 ⑧
const val x = 10 //编译错误 ⑨
}
代码第①行和第②行分别声明了两个顶层常量,它们都是运行期常量。代码第③行业试图声明StringBuilder类型的运行期顶层常量,但是这里会发生编译错误,因为运行期顶层常量只能是String或基本数据类型。代码第④行是在对象中声明常量,object UserDAO{}是对象声明,有关对象声明将在第11章详细介绍,这里不再赘述。代码第⑨行试图在函数中编译期常量,会发生编译错误,因为运行期常量用于顶层常量或对象中常量声明。
代码第⑤行和第⑧行会发生编译错误,因为这里试图修改_Hello1常量值。代码第⑥行和第⑦行是声明运行时常量。当然,运行期常量也可以声明为顶层的。
在这里插入图片描述
4.2.3 使用var还是val?
在开发过程中,有的时选择var还是val都能满足需求,那么选择哪一个更好呢?例如:可以将count变量声明为var或val。
val count = 3.14159
var count = 3.14159
在这里插入图片描述
val声明的引用类型示例代码如下:
//代码文件:chapter4/src/ch4.2.3.kt

class Person(val name: String, val age: Int) ①

public fun main(args: Array) {

val p1 = Person("Tony", 18)                            ② 

println(p1.name)
println(p1.age)

//p1 = Person("Tom", 20) //编译错误           ③

}
上述代码第①行定义了一个Person类,代码第②行是实例化Person类,实例化p1声明为val类型,不能改变p1的引用,代码第③行试图改变p1的引用,则会有编译错误,但是如果p1被声明为var的,则代码第③行可以编译通过。

4.3 注释

Kotlin程序有3类注释:单行注释(//)、多行注释(//)和文档注释(/**…*/)。注释方法与Java语言都类似,下面介绍一下单行注释和多行注释,文档注释将在第5章详细介绍。

1.单行注释
单行注释可以注释整行或者一行中的一部分,一般不用于连续多行的注释文本;当然,它也可以用来注释连续多行的代码段。以下是两种注释风格的例子:
if (x > 1) {
// 注释1
} else {
// 注释2
}

// if (x > 1) {
// // 注释1
// } else {
// // 注释2
// }
在这里插入图片描述
2.块注释
一般用于连续多行的注释文本,但也可以对单行进行注释。以下是几种注释风格的例子:
if (x > 1) {
/* 注释1 /
} else {
/
注释2 /
}
/

if (x > 1) {
} else {

}
*/

/*
if (x > 1) {
/* 注释1 / ①
} else {
/
注释2 */ ②
}
*/
Kotlin块注释可以嵌套,见代码第①行和第②行实现了块注释嵌套。
在这里插入图片描述
在程序代码中,对容易引起误解的代码进行注释是必要的,但应避免对已清晰表达信息的代码进行注释。需要注意的是,频繁的注释有时反映了代码的低质量。当觉得被迫要加注释的时候,不妨考虑一下重写代码使其更清晰。

4.4 语句与表达式

Kotlin代码是由关键字、标识符、语句和表达式等内容构成,语句和表达式是代码的重要组成部分。

4.4.1 语句
语句关注的代码执行过程,如for、while和do-while等。在Kotlin语言中,一条语句结束后可以不加分号,也可以加分号,但是有一种情况必须加分号,那就是多条语句写在一行的时候,需要通过分号来区别语句:
var a1: Int = 10; var a2: Int = 20;

4.4.2 表达式
表达式是一般位于赋值符(=)的右边,并且会返回明确的结果。下列代码中10和20是最简单形式的表达式。
var a1 = 10
val a2 = 20
在上述代码中,直接将表达式(10和20)赋值给变量或常量,并没有指定数据类型,这因为在Kotlin编译器可以根据上下文自动推断数据类型。上述代码也可以指定数据类型。
var a1: Int = 10
val a2: Int = 20
在上述代码中在变量标识符后面“冒号+数据类型”是为变量或常量指定数据类型,本例中是指定a1和a2为Int类型。
在这里插入图片描述
为了使代码更加简洁Kotlin将Java中一些语句进行简化,使之成为一种表达式,这些表达式包括:控制结构表达式、try表达式、表达式函数体和对象表达式。示例代码如下:
//代码文件:chapter4/src/ch4.4.2.kt

public fun main(args: Array) {

val englishScore = 95
val chineseScore = 98

//if控制结构表达式
val result = if (englishScore <60) "不及格" else "及格"             ①
println(result)

val totalScore = sum(englishScore,chineseScore)                   ②
println(totalScore)

//try表达式
val score = try {                        ③
    //TODO
} catch (e: Exception) {
    return
}

}
fun sum(a: Int, b: Int): Int = a + b
//表达式函数体 ④
上述代码第①行赋值使用了if控制结构表达式,在Kotlin中除了for、do和do-while等控制结构是语句外,大多数控制结构都是表达式,如when等。
代码第②行是调用代码第④行声明的sum函数,在sum函数中函数体,即a + b表达式没有放到一对大括号中,而是直接赋值给函数,这就是“表达式函数体”,表达式函数体会在10.2节详细介绍。
代码第③行是调用try表达式,try是用来捕获异常的,有关使用try表达式具体细节会在第18章详细介绍。

4.5 包

在程序代码中给类或函数起一个名字是非常重要的,但是有时候会出现非常尴尬的事情,名字会发生冲突,例如:项目中自定义了一个日期类,取名为Date,但是你可能会发现Kotlin核心库中还有多个Date,例如:位于java.util包和java.sql包中。

4.5.2 包作用
在Kotlin与Java一样为了防止类、接口、枚举、注释和函数等内容命名冲突引用了包(package)概念,包本质上命名空间(namespace)[1]。在包中可以定义一组相关的内容(类、接口、枚举、注释和函数),并为它们提供访问保护和命名空间管理。
在前面提到的Date类名称冲突问题,很好解决,将不同Date类放到不同的包中,自定义Date类可以放到自己定义的com.a51work6包中,这样就不会与java.util包和java.sql包中Date发生冲突问题了。
[2] 命名空间,也称名字空间、名称空间等,它表示着一个标识符(identifier)的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他命名空间中。
——引自于 维基百科 https://zh.wikipedia.org/wiki/命名空间

4.5.2 包定义
Kotlin中使用package语句定义包,package语句应该放在源文件的第一行,在每个源文件中只能有一个包定义语句。定义包语法格式如下:
package pkg1[.pkg2[.pkg3…]]
pkg1~ pkg3都是组成包名一部分,之间用点(.)连接,它们命名应该是合法的标识符,其次应该遵守Kotlin包命名规范,即全部小写字母。
定义包示例代码如下:
//代码文件:chapter4/src/com/a51work6/Date.kt
package com.a51work6

//定义Date类
class Date {

override fun toString(): String {
    return "公元2028年8月8日8时8分8秒"
}

}
//定义函数
fun add(a: Int, b: Int): Int = a + b
//表达式函数体
com.a51work6是自定义的包名,包名一般是公司域名的倒置。
在这里插入图片描述
如果在源文件中没有定义包,那么文件中定义的类、接口、枚举、注释和函数等内容将会被放进一个无名的包中,也称为默认包。
定义好包后,包采用层次结构管理这些内容,如图4-1所示是在IntelliJ
IDEA文件视图中查看包,可见有默认包和com.a51work6包。如果Windows资源管理器中查看这些包,会发现如图4-2所示的层次结构,<源文件目录>是根目录,也是默认包目录,可见其中有多个.kt文件。com是文件夹,a51work6子文件夹,在a51work6中包含一个Date.kt文件。Kotlin编译器把包对应于操作系统的文件目录来管理,不仅是源文件,编译之后的字节码文件也采用操作系统的文件目录管理的。
在这里插入图片描述
在这里插入图片描述

4.5.3 包引入
为了能够使用一个包中内容(类、接口、枚举、注释和函数),需要在Kotlin程序中明确引入该包。使用import语句引入包,import语句应位于package语句之后,所有类的声明之前,可以有0~n条import语句,其语法格式为:
import package1[.package2…].(内容名|)
“包名.内容名”形式只引入具体特定内容名,“包名.
”采用通配符,表示引入这个包下所有的内容。但从编程规范的角度提倡明确引入特定内容名,即“包名.内容名”形式可以提高程序的可读性。
如果需要在程序代码中使用com.a51work6包中Date类。示例代码如下:
//代码文件:chapter4/src/ch4.5.kt

import com.a51work6.Date //引入该包下Date类 ①
import com.a51work6.add //引入该包下add函数 ②
//import com.a51work6.* //引入该包下所有内容 ③
//import java.util.Date //引入该包下Date类 ④

public fun main(args: Array) {

val date =Date()                      ⑤   

System.out.println(date)
val now =java.util.Date() ⑥
println(now)

val totalScore= add(100, 97)        

println(totalScore)
}
上述代码第①行是引入com.a51work6中的Date类,代码第②行是引入com.a51work6中的add函数,而代码第③行是引入com.a51work6中的所有内容,它可以替代上面的两条import语句。
在这里插入图片描述

本章小结

本章主要介绍了Kotlin语言中最基本的语法,首先介绍了标识符和关键字,读者需要掌握标识符构成,了解Kotlin关键字的分类。然后介绍了Kotlin中的变量和常量,注意var、val和const val的区别。再然后介绍了注释,注释分为单行注释和块注释。接着介绍了语句和表达式,注意Kotlin中多种形式的表达式。最后介绍了包,其中理解包的作用,熟悉包的定义和引入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值