第二章:揭开Kotlin的基础面纱(二)

前言:在三月份的时候,打算写一本关于Kotlin语言的书,名字都起好了,叫《Kotlin进化之路》,发现,写着写着,自己却没有了那个耐性,索性,整理整理,在公众号里更新吧,这是一个系列,请大家跟上脚步~这篇更新的是:

《Kotlin进化之路》之【第二章:揭开Kotlin的基础面纱】(二)

2.1 基本数据类型

2.1.1:数据类型概括

在Kotlin 中,所有变量的成员方法和属性都是一个对象,一些类型是内建的,它们的实现是优化过的,但对用户来说它们就像普通的类一样,在这节中,将会讲到大多数的类型:数值,字符,布尔,以及数组。

Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等,会Java的同学觉着这个和Java类似,但需要注意的是,字符不属于数值类型,是一个独立的数据类型,具体的数据类型及位宽度,详见图2.1.1.1。

(图2.1.1.1)

上图中忽略了取值范围,其实这个学过Java的同学应该有所了解,对于刚接触到高级语言的同学可能略显生疏,下面我就在列一张表,仔细的来对比一下:

如何去表示一个字面常量,对于十进制的表示方法,我们都会,无非就是:123……,那么其它进制呢?

l16进制表示方法以0x开头:0x0F

这里有一点需要注意,Kotlin是不支持8进制的。

2.1.2:如何去定义一个常量或者变量

定义Kotlin的常量或者变量,它的语法和JavaScript的语法有点类似,用var来定义可变变量,用val来定义不可变变量,基本语法如下:

Var:=

Val:=

在Kotlin中val代表只读,var代表可变,对于这两个,开发中如果你暂时不知道用哪个的时候,我的建议是尽可能多的使用val,因为val是线程安全的,并且必须在定义时初始化,所以不需要担心 null 的问题,只需要注意 val 在某些情况下也是可变的就行了。

对于区别,我的理解如下:

val 和 var 是用于表示属性是否有 getter/setter:

var:同时有 getter 和 setter

val:只有 getter

所以,能用val的地方就用val。

具体使用如下:

vara : Int =66

valb : Int =88

【须知】如果变量或常量的数据类型,有可能采用自动类型推导,那么我们就可以省去类型,直接去赋值也是可以的,这样显得代码更加的简洁:

vala =66

valb =88

注意:由于val是不可变的,如果我们再次赋值,那么就会在编译之前出一个错误:Val cannot be reassigned,提示我们这个不能再重新分配:如图2.1.2.1。

(图2.1.2.1)

对于上面的一小段代码,可能有的同学蒙了,咋没有分号做结尾呢,这里需要说明一点的是,kotlin取消了分割语句的分号,而选择在换行时检查当前parser状态以及下一行第一个token决定是否结束语句,这个和Python的语法有点类似。

对于标识符这里我简单啰嗦几句,在实际的开发中,我希望大家能词能达意,也就是说,自己取得名字得符合公司的规定,让人有一种,见了这个标识符,就知道这个变量或者常量是干嘛用的,当然了,这里的标识符我为了方便,就简单化了。

²所有的标识符都应该以字母(A-Z或者a-z)、或者下划线(_)开始

²首字符之后可以是字母(A-Z或者a-z),下划线(_)或数字的任何字符组合

²关键字不能用作标识符

²标识符是大小写敏感的

²合法标识符举例:age、_value、__1_value

²非法标识符举例:123abc、-salary

举例2.1.2.1,输出各个类型的数据:

打印结果:

对于数据特别大的情况下,比如1000000000这个数值,为了显示的有层次美观,我们可以进行下划线来表示:

vala =1_000_000_000

println(a)

打印结果:

同样,其它类型的数据也可以这样操作,举例2.1.2.2:

funmain(args: Array) {

vala =888_888_888_888L

valb =666_666_666L

valc =0xFF_EC_DE_5E

vald =0b11010010_01101001_10010100_10010010

println(a)

println(b)

println(c)

println(d)

}

打印结果:

888888888888

666666666

4293713502

3530134674

2.1.3:静态类型(理解)

Kotlin 和 Java 一样是一种静态类型的编程语言,这意味着所有表达式的类型在编译期已经确定了,而编译器就能验证对象是否包含了你想访问的方法或者字段。

这与动态类型的编程语言形成了鲜明的对比,后者在JVM 上的代表包括 Groovy 和 JRuby。这些语言允许你定义可以存储任何数据类型的变量,或者返回任 何数据类型的函数,并在运行时才解析方法和字段引用。这会减少代码量并增加创 建数据结构的灵活性。但它的缺点是,在编译期不能发现像名字拼写错误这样的问题,继而导致运行时的错误。

另一方面,与Java 不同的是,Kotlin 不需要你在源代码中显式地声明每个变量 的类型。很多情况下,变量类型可以根据上下文来自动判断,这样就可以省略类型声明。这里有一个可能是最简单的例子 :

val x = 1

在声明这个变量时,由于变量初始化为整型值,Kotlin 自动判断出它的类型是 Int。编译器这种从上下文推断变量类型的能力被称作类型推导。

下面罗列了一些静态类型带来的好处:

性能——方法调用速度更快,因为不需要在运行时才来判断调用的是哪个方法。

可靠性——编译器验证了程序的正确性,因而运行时崩溃的概率更低。

可维护性——陌生代码更容易维护,因为你可以看到代码中用到的对象的类型。

工具支持——静态类型使 IDE 能提供可靠的重构、精确的代码补全以及其他 特性。

得益于Kotlin 对类型推导的支持,你不再需要显式地声明类型,因此大部分关 于静态类型的额外冗长代码也就不复存在了。

当你检视Kotlin 类型系统的细节时,你会发现许多熟悉的概念,类、接口以及 泛型和 Java 非常接近,所以大部分的 Java 知识可以很容易地转移到 Kotlin,然而, 也会有一些新概念出现。

其中最重要的概念是Kotlin 对可空类型的支持,通过在编译期检测可能存在的 空指针异常,它让你可以写出更可靠的程序。

另一个Kotlin 类型系统的新概念是对函数类型的支持,要搞清楚这一点,我们先要了解函数式编程的主要思想,以及 Kotlin 是如何支持这种编程风格的。

2.1.4:类型转换

在开发中,我们经常会遇到数据类型之间的转换,在Kotlin中由于表示方法的不同,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型,意味着在不进行显示转换的情况下我们不可以把Byte类型赋值给一个Int类型,如图2.1.4.1:

(图2.1.4.1)

2.1.4.1:显示转换

较小的类型不会被隐式转换为更大的类型,故而系统提供了显式转换,提供的显式转换方法如下:

ØtoByte() =>转换为字节型

ØtoShort() =>转换为短整型

ØtoInt() =>转换为整型

ØtoLong() =>转换为长整型

ØtoFloat() =>转换为浮点型

ØtoDouble() =>转换为双精度浮点型

ØtoChar() =>转换为字符型

ØtoString() =>转换为字符串型

举例2.1.4.1:

funmain(args: Array) {

vara: Int =88

println(a.toByte())

println(a.toShort())

println(a.toInt())

println(a.toLong())

println(a.toFloat())

println(a.toDouble())

println(a.toChar())

println(a.toString())

}

打印结果:

2.1.4.2:隐式转换

类型是从上下文推断出来的,即算术运算则被重载为适当的转换

举例2.1.4.2:

funmain(args: Array) {

valnum =88L+88//Long + Int => Long

print(num)

}

打印结果:

176

2.1.5:字符型(Char)

和Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ' 包含起来的,比如普通字符 '0','a'。

funmain(args: Array) {

varchar1: Char

char1 ='a'

char1 =1//这句代码会直接出错

println("char1 =>$char1")

}

字符型的变量不仅可以转换为数字,同时也可转换为其他类型,举例2.1.5.1:

funmain(args: Array) {

varchar1:Char='a'

varvar1 = char1.toByte()

varvar2 = char1.toInt()

varvar3 = char1.toString()

varvar4 = char1.toFloat()

varvar5 = char1.toShort()

println("var1 =>$var1\nvar2 =>$var2\nvar3 =>$var3\nvar4 =>$var4\nvar5 =>$var5")

}

打印结果:

var1 =>97

var2 =>97

var3 => a

var4 =>97.0

var5 =>97

除了可以转换类型外,当变量为英文字母时还支持大小写转换,举例2.1.5.2:

funmain(args: Array) {

/*

当字符变量为英文字母时,大小写的转换

*/

varcharA: Char ='a'

varcharB: Char ='B'

varcharNum: Char ='1'

varresult: Char

// 转换为大写

result = charA.toUpperCase()

println("result =>$result")

// 转换为小写

result = charB.toLowerCase()

println("result =>$result")

//当字符变量不为英文字母时,转换无效

result = charNum.toLowerCase()

println("result =>$result")

}

打印结果:

result => A

result => b

result =>1

字符转义同Java一样,使用某些特殊的字符时,要使用转义。下列是支持的转义序列:

Ø\t => 表示制表符

Ø\n => 表示换行符

Ø\b => 表示退格键(键盘上的Back建)

Ø\r => 表示键盘上的Enter键

Ø\\ => 表示反斜杠

Ø\' => 表示单引号

Ø\" => 表示双引号

Ø\$ => 表示美元符号,如果不转义在kotlin中就表示变量的引用了

Ø其他的任何字符请使用Unicode转义序列语法。例:'\uFF00'

举例2.1.5.3:

funmain(args: Array) {

println("\n换行符")

println("\t制表符")

println("\b退格键")

println("\rEnter键同样换行")

println('\\')

println('\'')

println('\"')

println('\$')

println('\uFF01')

}

打印结果:

换行符

制表符

退格键

Enter键同样换行

\

'

"

$

2.1.6:布尔类型(Boolean)

Boolean关键字表示布尔类型,并且其值有true和false

举例2.1.6.1:

funmain(args: Array) {

varboolTrue:Boolean=true

varboolFalse:Boolean=false

println(boolTrue)

println(boolFalse)

}

打印结果:

true

false

2.1.7:可空类型

一门新的语言的诞生总有它特定的和别的语言不同的一点,Kotlin也不例外,Kotlin语言与Swift语言类似,默认情况下所有的数据类型都是非空类型(Non-Null),声明的变量都是不能接收空值(null)的,这一点与Java和Objective-C等语言有很大的不同。

Kotlin的非空类型设计可以防止空指针异常(NullPointerException),在Kotlin中如果将一个对象的声明为非空类型,那么它就永远不会接收空值,否则会发生编译错误。

代码演示:

funmain(args: Array) {

vara:Int =66

a =null

}

上述代码会抛出一个异常,因为Int是非空类型,它所声明的变量a不能接收空值,但有些场景确实没有数据,例如查询数据库记录时,没有查询出符合条件的数据是很正常的事情,为此,Kotlin为每一种非空类型提供对应的可空类型(Nullable),就是在非空类型后面加上问号(?)表示可空类型。

修改后代码则就没有了问题:

funmain(args: Array) {

vara:Int? =66

a =null

}

Int?是可空类型,它所声明的变量a可以接收空值,可空类型在具体使用时会有一些限制:

Ø不能直接调用可空类型对象的函数或属性。

Ø不能把可空类型数据赋值给非空类型变量。

Ø不能把可空类型数据传递给非空类型参数的函数。

为了“突破”这些限制,Kotlin提供了如下运算符:

Ø安全调用运算符:?.

Ø安全转换运算符:as?

ØElvis运算符:?:

Ø非空断言:!!

Ø此外,还一个let函数帮助处理可空类型数据。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180504G1H32F00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券