Kotlin 知识梳理 | 基础概念一览

Posted 伯特说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin 知识梳理 | 基础概念一览相关的知识,希望对你有一定的参考价值。

好文章不怕没人看,还有收益

  

Kotlin 知识梳理(1) | 基础概念一览



本文是对《Kotlin in Action》的学习笔记,如果需要运行相应的代码可以访问在线环境 try.kotlinlang.org,这部分的思维导图为:


Kotlin 知识梳理(1) | 基础概念一览



一、函数

01

函数的基本构成


在Kotlin中,函数的基本结构由四个部分构成:

  • 函数名称

  • 参数列表

  • 返回类型

  • 函数体


函数的声明以关键字 fun 开始,函数名称紧随其后,接下来是括号括起来的参数列表,参数列表的后面跟着返回类型,返回类型和参数列表之间用冒号隔开,最后是函数体。


下面是一个比较大小的函数例子,上面谈到的四个部分构成如图中标注所示:


Kotlin 知识梳理(1) | 基础概念一览

02

表达式和语句


在上面的例子中,if是表达式,而不是语句。表达式和语句的区别在于:


  • 表达式:有值,并且能作为另一个表达式的一部分使用。

  • 语句:总是包含着它的代码块中的顶层元素,并且没有自己的值。


在Java中,所有的控制结构都是语句,而在Kotlin中,除了for、do和do/while以外大多数控制结构都是表达式。


当函数体是由单个表达式构成时,可以用这个表达式作为完整的函数体,并且去掉花括号和return语句,上面的例子就是这种情况,因此可以改写为:


Kotlin 知识梳理(1) | 基础概念一览


注:

  • 如果函数体写在花括号中,我们说这个函数有代码块体。

  • 如果它直接返回了一个表达式,它就有表达式体。

03

省略返回类型


对于表达式体函数,可以省略返回类型,因为编译器会分析作为函数体的表达式,并把它的类型作为函数的返回类型,这种分析称为类型推导。但是对于有返回值的代码块体函数,必须显示地写出返回类型和return语句。


上面的例子可以简化为:


Kotlin 知识梳理(1) | 基础概念一览


二、变量


在Kotlin中,变量的声明以关键字val/var开始,然后是变量名称,最后可以加上类型(不加也可以),这里分为两种情况:


  • 如果指定了初始化器,那么在不指定类型的情况下,编译器会分析初始化器表达式的值,并把它的类型作为变量的类型,例如下面两个就分别为Int和Double类型:


    Kotlin 知识梳理(1) | 基础概念一览


  • 如果没有指定初始化器,需要显示地指定它的类型,因为此时编译器无法推断出它的类型。


    Kotlin 知识梳理(1) | 基础概念一览

01

可变变量和不可变变量

声明变量的关键字有两个:


(1) 不可变引用 val

使用val声明的变量不能在初始化之后再次赋值,它对应的是Java的final变量。

默认情况下,应该尽可能地使用val关键字来声明所有的Kotlin变量。在定义了val变量的代码块执行期间,val变量只能进行唯一一次初始化,但是,如果编译器能确保唯一一条初始化语句会被执行,可以根据条件使用不同的值来初始化它。


Kotlin 知识梳理(1) | 基础概念一览


(2) 可变引用 var

这种变量的值可以改变,但是它的类型却是改变不了的。


Kotlin 知识梳理(1) | 基础概念一览


如果需要在变量中存储不匹配类型的值,必须手动把值转换或强制转换到正确的类型。

02

字符串模板

Kotlin可以在字符串字面值中引用局部变量,只需要在变量名称前面加上字符$。


Kotlin 知识梳理(1) | 基础概念一览


如果要在字符串中使用$,需要对它进行转义。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


除了可以引用局部变量之外,还可以引用更加复杂的表达式,只需要把表达式用花括号扩起来。


Kotlin 知识梳理(1) | 基础概念一览


三、类

类的概念就是把数据和处理数据的代码封装成一个单一的实体,在Java中,数据存储在字段中,并且通常是私有的。如果想让类的使用者访问到数据得提供访问方法,即getter/setter。

01

属性


在Java中,字段和其访问器的组合常常被叫作属性。在Kotlin中,属性是头等的语言特性,完全 替代了字段和访问器方法。在类中声明一个属性和声明一个变量一样:使用val/var关键字,前者是只读的,而后者是可变的。


当声明属性的时候,就声明了对应的访问器(只读属性有一个gettter,而可变属性则有getter/setter),例如下面的例子,声明了只读的name属性,可变的isMarried属性,其赋值和读取的方法如下所示:


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览

02

自定义访问器


假设声明一个矩形,它能判断自己是否是正方形,那么就不需要一个单独的字段来存储这个信息,此时我们可以写一个自定义的访问器:用val开头作为声明,紧跟着的是属性的名称和类型,接下来是get()关键字,最后是一个函数体。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览

03

目录和包


1. Kotlin中包的概念和Java类似,每个kotlin文件都能以一个package语句开头,而文件中定义的所有声明(类、函数及属性)都会被放到这个包中。


2. 如果其他文件定义的声明也有相同的包,这个文件可以直接使用它们;如果包不同,则需要导入它们,导入语句放在文件的最前面并使用import关键字。


3. kotlin不区分导入的是类还是函数,而且,它允许使用import关键字导入任何种类的声明,可以直接导入顶层函数的名称,也可以在包名称后加上.*来导入特定包中定义的所有声明。


4. 在Java中,要把类放到和包结构相匹配的文件与目录结构中,而在kotlin中,可以把多个package声明不相同的类放在同一个文件夹中。


四、表示和处理选择:枚举和when

01

声明枚举类

(1)简单枚举类

声明枚举类时,enum是一个所谓的软关键字,只有当它出现在class前面时才有特殊的意义,在其他地方可以当做普通名称使用。而class仍然是一个关键字,下面是一个枚举类的声明:


Kotlin 知识梳理(1) | 基础概念一览


(2)带属性的枚举类

以下是一个带属性的枚举类:


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


当声明一个带属性的枚举类时,有几点需要注意:


  • 当声明每个枚举常量的时候,必须提供该常量的属性值。

  • 如果要在枚举类中定义任何方法,就要使用分号把枚举常量列表和方法分开。

02

使用 "when” 处理枚举类


when是一个有返回值的表达式,因此,作为表达式函数体,它可以去掉花括号和return语句,并省略返回类型的声明。


下面是一个通过when处理枚举类的例子,它和Java中的switch语句类似,根据when中Color的值走到对应的分支,除此之外,我们可以把多个值用逗号间隔,合并到同一个分支:


Kotlin 知识梳理(1) | 基础概念一览


运行的结果为:


Kotlin 知识梳理(1) | 基础概念一览

03

在 “when”结构中使用任意对象


在Java中,和when类似的switch语句要求必须使用常量(枚举常量、字符串或者数字字面值)作为 分支条件,而when允许使用任何对象,我们使用一个函数来混合两种颜色。


下面例子中用到的setOf是由Kotlin标准函数库提供的,它可以创建出一个Set,并且会包含所有指定为函数实参的对象,只要两个set中包含一样的条目,它们就是相等的,集合的条目顺序并不重要。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


除此之外,我们还可以不给when表达式提供参数,这样分支条件就是任意的布尔表达时,这种写法的优点是不会创建额外的对象,但代价是它更难理解。

04

智能转换:合并类型检查和转换


在kotlin中,判断一个变量是否是某种类型需要使用is关键字,它和Java当中的instanceOf相似:


  • 在Java中,在检查完后还需要显示地加上类型转换。

  • 在kotlin中,如果你检查过一个变量是某种类型,后面就不需要再转换它,可以把它当做你检查过的类型来使用。


我们用下面这个例子,Num和Sum都实现了Expr接口,通过is判断它的类型,完成递归求和。可以看到,在is判断之后,不再需要转换成Num或Sum,就可以直接访问该类的成员变量。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


智能转换 只在变量经过is检查且之后不再发生变化 的情况下有效,当你对一个类的属性进行智能转换的时候,这个属性必须是一个val属性,而且不能有自定义的访问器,否则,每次对属性的访问是否都能返回同样的值将无从验证。

05

代码块作为 "if" 和 "when" 的分支


if和when都可以使用代码块作为分支体,这种情况下,代码块中的最后一个表达式就是结果,这个规则在所有使用代码块并期望得到一个结果的地方成立。同样的规则对try主体和catch子句也有效。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


五、迭代事务


01

while 循环


kotlin和Java一样,有while循环和do-while循环,它们的语法和Java中相应的循环完全一致。

02

迭代数字:区间和数列

在Java当中,对于循环的处理方式为:先初始化变量,在循环的每一步更新它的值,并在值满足某个限制条件时退出循环。


而在Kotlin中,为了替代常见的循环用法,使用了 区间 的概念,其本质上就是两个值之间的间隔,这两个值通常是数字:一个起始值,一个结束值。使用..运算符来表示区间,而结束值始终是区间的一部分。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


除此之外,还有downTo、step和until等用于区间的语法,用于进行循环操作,例如下面的例子downTo用于递减到指定的值,而step则指定步长:


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


使用until则可以使迭代不包含指定的结束值,例如下面这样:


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览

03

迭代 map


1. 更新 map

这里我们用到了TreeMap,在更新map时,我们可以像使用数组一样,只不过下标变成了key值:


Kotlin 知识梳理(1) | 基础概念一览


2. 访问 map

下面的例子展示了for允许允许展开迭代中的集合的元素,把展开的结果存储到了两个独立的变量中:letter是键、binary是值:


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


04

使用 "in" 检查集合和区间的成员


使用in运算符来检查一个值是否在区间中,或者它的逆运算!in来检查这个值是否不在区间中,区间不仅限于字符,假如有一个支持实例比较操作的任意类(实现了java.lang.Comparable接口),就能创建这种类型的对象的区间。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


六、Kotlin 中的异常


kotlin的异常处理和Java以及其他许多语言的处理方式类似:一个函数可以正常结束,也可以在出现错误的情况下抛出异常。方法的调用者能捕获到这个异常并处理它;如果没有处理,异常会沿着调用栈再次抛出。


  • 抛出异常时使用throw关键字,但是不必使用new关键字来创建异常实例。

  • throw结构是一个表达式,能作为另一个表达式的一部分使用。

01

“try” "catch" 和 "finally"


当使用带有catch和finally子句的try结构来处理异常时,下面是一个典型的结构:


Kotlin 知识梳理(1) | 基础概念一览


和Java最大区别就是throws子句没有出现在代码中:如果使用Java来写这个函数,你会显示地在函数声明上面写上throws IOException。这是因为IOException是一个受检异常,在Java中,这种异常必须显示地处理,必须声明你的函数能抛出所有的受检异常。


Kotlin 知识梳理(1) | 基础概念一览

Java 处理方式


kotlin不区分受检异常和未受检异常,不必指定函数抛出的异常,而且可以处理也可以不处理异常。


与此同时,BufferReader.close可能抛出需要处理的受检异常,如果关闭失败,大多数程序不会采取什么有意义的行动,所以捕获来自close方法的异常所需的代码是多余的。

02

“try”作为表达式


kotlin中的try关键字就像if和when一样,引入了一个表达式,可以把它的值赋给一个变量,并且需要用花括号把语句主体括起来。如果主体包含多个表达式,那么整个try表达式的值就是最后一个表达式的值。


Kotlin 知识梳理(1) | 基础概念一览


运行结果为:


Kotlin 知识梳理(1) | 基础概念一览


END


Kotlin 知识梳理(1) | 基础概念一览


我的好友 Tamic 在 GitChat 上,做了一个主题为“普通程序员,如何两年做到月薪 20k+”的分享。我在这里推荐给大家,也希望能够对一些正在追求编程路上的程序员有一定的帮助。


关于 Tamic:

我奎哥,参与过千万级日活百度浏览器 App 的开发,参与过平安某知名 App 的架构,有知名技术公司和知名金融公司的经历!长期在 CSDN 和简书分享技术原创,职业思维原创等,让许多程序员得到知识成长!


感兴趣的识别邀请卡中二维码参与 Chat :


Kotlin 知识梳理(1) | 基础概念一览


1. 关注并后台回复 Kotlin,送优质学习资源


2. 精彩推荐:



Kotlin 知识梳理(1) | 基础概念一览

感谢点赞或转发分享

扫码关注,及时获取推送

Kotlin 知识梳理(1) | 基础概念一览

有帮助?点击右上角 


点击“阅读原文”,查看更多内容

以上是关于Kotlin 知识梳理 | 基础概念一览的主要内容,如果未能解决你的问题,请参考以下文章

Android面试知识梳理(面试官及面试者)

知识点梳理

web基础知识梳理(笔记)

帮你梳理正则表达式的基础知识

SQL- 基础知识梳理 - 存储过程

SQL- 基础知识梳理 - 游标