网页链接:https://kotlinlang.org/docs/reference/basic-types.html

2.   基本概念

2.1.  基本类型

从可以在任何变量处理调用成员函数和属性角度来说,在Kotlin开发语言中,一切都是对象。有些类型是内嵌的,它们的实现进行过优化,用户看到的仍是原始类。在这节中,我们说明大部分这些类型:数字,字符,布尔和数组。

2.1.1.   数字

Kotlin开发语言处理数组的方法类似Java开发语言,但是也有差别。例如,没有隐含的数字扩宽的转换,并且在相同的情况下,文字也有些不同。

Kotlin开发语言提供下列内嵌类型表示数字(这是类似Java开发语言):

类型

位宽度

Double

64

Float

32

Long

64

Int

32

Short

16

Byte

8

注意,在Kotlin开发语言中,字符不属于数组。

2.1.1.1. 文字常数

对于整数值有下面几种文字常数:

—— 十进制数:123

—— 附加大写字母L标准长整数:123L

—— 十六进制数:0x0F

—— 二进制数:0b00001011

注意:不支持八进制数字。

Kotlin开发语言还支持通用的浮点数表示法:

—— 默认是双精度:123.5,123.5e10

—— 附加f或F表示单精度浮点数:123.5F

2.1.1.2. 表示法

在Java开发语言平台上,数字是作为JVM基本类型进行物理存在的,除非需要一个可null数字引用(如:Int?)或包含在泛型。后一种情况下,是将数字装箱的。

注意数字装箱不保持一致性:

 val a: Int = 10000
print(a === a) // 打印 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!打印 'false'!!!

而另一方面,却保持相等:

 val a: Int = 10000
print(a == a) // 打印 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA == anotherBoxedA) // 打印 'true'

2.1.1.3. 显式转换

由于不同的表示法,较小类型不是较大类型的子类型。如果是,就有下列麻烦了:

 // 假设代码,没有实际编译:
val a: Int? = 1 // 装箱为Int (java.lang.Integer)
val b: Long? = a // 隐含转换装箱为Long (java.lang.Long)
print(a == b) // 令人惊讶! 当equals()检查其它部分不是Long,就打印"false"

所以不仅仅是一致性,而且即使相当也会在此默默丢失一部分。

这样,较小的类型不会隐含的转换为较大的类型。这就是说,如果没有进行明确的类型转换,Byte类型值是不能赋值给Int类型变量。

 val b: Byte = 1 // OK, 静态文字检查
val i: Int = b // 错误

可以进行明确(显式)的数字宽度转换:

 val i: Int = b.toInt() // OK: 显式宽度转换

每项数字类型支持下列转换:

toByte(): Byte

—toShort(): Short

—toInt(): Int

—toLong(): Long

—toFloat(): Float

—toDouble(): Double

—toChar(): Char

因为类型是从上下文推断,以及适当的转换重载了算术运算符,所以隐式转换缺位是很少引人注目的,例如:

 val l = 1L + 3 // Long + Int => Long

2.1.1.4. 运算

Kotlin开发语言支持对数字标准的一套运算,它们被声明为相应类成员(但是,编译器优化调用的相应指令)。查看:运算符重载(5.6)。

作为位运算,对于它们没有特殊特性(字符),仅仅命名函数使其能以中缀方式被调用,如:

 val x = (1 shl 2) and 0x000FF000

这是完整的位运算列表(仅仅对Int和Long类型有效):

— shl(bits) – signed shift left (Java’s <<)

— shr(bits) – signed shift right (Java’s >>)

— ushr(bits) – unsigned shift right (Java’s >>>)

— and(bits) – bitwise and

— or(bits) – bitwise or

— xor(bits) – bitwise xor

— inv() – bitwise inversion

2.1.2.   字符

char类型表示字符。它们不能直接作为数组处理:

 fun check(c: Char) {
if (c == 1) { // ERROR: incompatible types
// ...
}
}

字符文字是在单引号中:’1’,’\n’,’\uFF00’。我们能够明确地转换字符到Int数字:

 fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // Explicit conversions to numbers
}

在需要可null引用时,像数字、字符是被装箱。装箱操作是不保证一致性的。

2.1.3.   布尔值

Boolean类型表示布尔值,它有两个值:true和false。

如果需要可null引用时,布尔值可以被装箱的。

布尔值的内置的运算包括:

— || – lazy分离 (注:这个“lazy”不知道怎样翻译好,就是 “或”为啥要这样?)

— && – lazy连接

— ! – 非

2.1.4.   数组

在Kotlin开发语言中,Array类表示数组,它有get和set函数(即通过操作符重载约定转成[]),有size属性,以及其他一些有用的成员函数:

 class Array<T> private constructor() {
val size: Int
fun get(index: Int): T
fun set(index: Int, value: T): Unit fun iterator(): Iterator<T>
// ...
}

可以用库函数arrayOf(),将数组各项的数值传递给它,来创建一个数组,如:arrayOf(1,2,3)创建数组[1,2,3]。或者,用arrayOfNulls()库函数创建一个指定尺寸(size)的数组,其元素均填充为null。

另一种选择是用工厂函数获得数组尺寸,并且返回指定索引位置的数组元素的初始值:

 // Creates an Array<String> with values ["0", "1", "4", "9", "16"]
val asc = Array(5, { i -> (i * i).toString() })

如上所述,[]操作符表示调用成员函数get()和set()。

注意:与Java开发语言不同,在Kotlin开发语言中,数组是不变量。这意味着kotlin开发语言不允许赋值Array<String>到Array<Any>,这防止运行的可能的错误(但是,可以用Array<out Any>,查看:类型推测(3.7.2))。

Kotlin开发语言也有专用类表示原始类型的数组,不需要装箱消耗:ByteArray、ShortArray、IntArray等等。这些类与Array类没有继承关系,但是它们有相同的一组方法和属性。它们中的每一个都有相应的工厂函数:

 val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]

2.1.5.   串

String类型表示串。String是不可变的。串的元素是字符,可以用索引操作访问:s[i]。可以用for循环遍历一个串:

 for (c in str) {
println(c)
}

2.1.5.1. 串文字

Kotlin开发语言有两种串文字类型:包含转义字符的转义串和包含任意字符和新行符的原始串。转义串非常像Java开发语言的串:

 val s = "Hello, world!\n"

转义可以用习惯的方法(用\)实现。

原始串由三引号(”””)定界的,包含非转义字符、新行符,以及其它任意字符:

 val text = """
for (c in "foo")
print(c)
"""

2.1.5.2. 串模板

串可以包含模板表达式,即:可计算的代码片段,其结果链接到串中。模板表达式以美元符号($)开始,和简单的名字构成:

 val i = 10
val s = "i = $i" // 计算结果是 "i = 10"

或是在大括号中的任意表达式:

 val s = "abc"
val str = "$s.length is ${s.length}" // 计算结果是 "abc.length is 3"

在原始串和转义串中,都支持模板。如果需要表达$字符文字,则可以用下列语法:

 val price = "${'$'}9.99"

2.2.  包

一个源文件可以是从声明包开始的:

 package foo.bar

 fun baz() {}
class Goo {}
// ...

源文件中的所有内容(如:类和函数)都包含在包的声明中。所以,在上面例子中,baz()的完整名称是foo.bar.baz,Goo的完整名称是foo.bar.Goo。

如果源文件中没有指明包,则这个文件中的内容属于没有名称的“默认”包。

2.2.1.   导入(import)

除默认的import外,每个文件都可以有自己的import伪指令。Import的句法在语法(6.2)中描述了。

我们既可以导入单个名称,如:

 import foo.Bar // Bar is now accessible without qualification

也可以是范围内所有可访问的内容(包、类、对象等等):

 import foo.* // everything in 'foo' becomes accessible

如果有命名冲突,可以在冲突项用as关键字重命名来消除:

 import foo.Bar // Bar可以访问
import bar.Bar as bBar // bBar 表示 'bar.Bar'

import关键字不限制导入的类;也可以用途导入其它声明:

—— 顶层函数和属性;

—— 在对象声明(3.12.2)中声明的函数和属性;

—— 枚举常数(3.11);

不像Java开发语言,Kotlin开发语言没有独立的“import static”句法;所有这些声明都是用常规的import关键字来导入。

2.2.2.   顶层声明的可视范围

如果顶层声明标注private,它是它所在文件的私有的(查看:可视性修饰符(3.4))

2.3.  控制流

2.3.1.   if表达式

在Kotlin开发语言中,if是一个表达式,即:它返回一个值。由于在此规则下普通if运行的很好,因此没有三元运算符(?:else)。

 // 传统用法
var max = a
if (a < b)
max = b // 带else
var max: Int
if (a > b)
max = a
else
max = b // 作为表达式
val max = if (a > b) a else b

if分支可以是代码块,最后表达式是代码块的值:

 val max = if (a > b) {
print("Choose a")
a
}
else {
print("Choose b")
b
}

如果用if作为表达式,而不是语句(例如,返回它的值,或赋值给变量),表达式要求有else分支。

查看:if语法(6.2.3.4)

2.3.2.   when表达式

When替代了类似C开发语言的switch操作符。最简单形式如此:

 when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}

when将变量与其的所有分支顺序逐一匹配,直至找到条件相符的分支。when即可用作表达式,也可以用作语句,满足条件的分支值就是整个表达式的值。如果它用作语句,个别分支的值将被忽略。(就如同if,每个分支可以是一个代码块,代码块中最后的表达式值就是其值。)

else分支等价与没有其它分支满足条件。如果when用作一个表达式,且编译器无法验证分支条件覆盖了所有的可能情况,则强制性要求else分支。

如果多种情况都有相同的处理方法,也可以用逗号将分支条件组合起来:

 when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

可以用任意表达式(不仅仅是常数)作为分支条件:

 when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}

还可以用in或!in检查一个范围(5.2)或集合:

 when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

另一种情况,可以用is或!is检查特别类型。注意,由于智能转换(5.4),不需要任何额外的检查就可以访问类型的方法和属性:

 val hasPrefix = when(x) {
is String -> x.startsWith("prefix")
else -> false
}

when还可以用来替换if-else链。如果没有变量,分支条件就是简单的布尔表达式,且在when条件为true时,执行该分支:

 when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}

查看:when语法(6.2.3.4.2.1)。

2.3.3.   for循环

for循环遍历提供的任何一个迭代器。句法如下:

 for (item in collection)
print(item)

循环体可以是一个代码块。

 for (item: Int in ints) {
// ...
}

如前所述,for循环遍历提供的任何一个迭代器,即:

—— 有成员iterator()或扩展函数iterator(),它返回类型:

 —— 有成员next()或扩展函数next(),和

 —— 有返回布尔类型的成员hasNext()或扩展函数hasNext()。

所有这三个函数是需要作为操作符的。

如果要利用索引遍历一个数组或列表,可以这样做:

 for (i in array.indices)
print(array[i])

注意,这句“遍历一个范围”是由编译器优化实现的,不需要产生额外的对象。

或者,可以用withIndex库函数:

 for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}

查看:for语法(6.2.3.3)。

2.3.4.   while循环

while和do…while都是如常规一样工作:

 while (x > 0) {
x--
} do {
val y = retrieveData()
} while (y != null) // y is visible here!

查看:while语法(6.2.3.3)。

2.3.5.   循环的中断和继续

Kotlin开发语言支持循环中的传统break和continue操作符。查看:返回和跳转(2.4)。

2.4.  返回和跳转

Kotlin开发语言有三种结构化的跳转操作符:

—— return。默认情况下,由最近的函数返回,或匿名函数的返回。

—— break。终止最近一层循环。

—— continue。继续最近一层循环的下一步。

2.4.1.   中断和继续标签

在Kotlin开发语言中,任何表达式都可以带标签。标签的格式是在标识符后跟@来表示,如:abc@,fooBar@都是合法的标签(查看:语法(6.2))。为了标记表达式,只需要在其前面加上标签即可:

 loop@ for (i in 1..100) {
// ...
}

现在,就可以break或continue到标签了:

 loop@ for (i in 1..100) {
for (j in 1..100) {
if (...)
break@loop
}
}

带有标签的break跳转到标记loop之后的执行点。Continue继续进行标记loop的下一步。

2.4.2.   在标签处返回

Kotlin开发语言在函数体、局部函数和对象表达式中,允许函数嵌套。Return允许我们有外部函数返回。最重要的用例是由Lambda表达式返回。我们这样编写回调:

 fun foo() {
ints.forEach {
if (it == 0) return
print(it)
}
}

返回表达式是由最近函数返回,即:foo。(注意:这样对Lambda表达式仅支持非局部返回到内嵌函数(4.1.5)。)如果要从Lambda表达式返回,就需要标记它限制返回:

 fun foo() {
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
}

现在,就仅从Lambda表达式返回。通常,最方便的是用隐含标签:这样标签与传递给Lambda表达式的函数同名。

 fun foo() {
ints.forEach {
if (it == 0) return@forEach
print(it)
}
}

或者,可以用匿名函数(4.2.3.3)替代Lambda表达式。在匿名函数中的return语句是从匿名函数自身返回。

 fun foo() {
ints.forEach(fun(value: Int) {
if (value == 0) return
print(value)
})
}

当返回一个值是,解析器优先给出恰当的返回,如:

 return@a 1

就是“在标签@a处返回1”而不是“返回标签表达式(@a 1)”。

KOTLIN开发语言文档(官方文档) -- 2.基本概念的更多相关文章

  1. KOTLIN开发语言文档(官方文档) -- 入门

    网页链接:https://kotlinlang.org/docs/reference/basic-syntax.html 1.   入门 1.1.  基本语法 1.1.1.   定义包 包说明应该在源 ...

  2. Kotlin开发语言文档(官方文档)-- 目录

    开始阅读Kotlin官方文档.先上文档目录.有些内容还未阅读,有些目录标目翻译还需琢磨琢磨.后续再将具体内容的链接逐步加上. 文档链接:https://kotlinlang.org/docs/kotl ...

  3. OpenGL ES着色器语言之着色概览(官方文档)

    OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...

  4. Spring WebSocket Support官方文档+翻译

    实时更新技术能够应用在很多场景中,比如在浏览器中聊天.股票报价.状态更新.现场直播.这些需求对时间的延迟性都很敏感,但是我们可以发现他们存在这共有的共性. 标准的HTTP请求,是一次请求对应一次相应. ...

  5. kotlin官方文档-1.0入门

    什么是Kotlin?   图片发自简书App Kotlin是JetBrains开发的基于JVM的语言,JetBrains想必大家应该很熟悉了,他们创造了很多强大的IDE,android studio谷 ...

  6. iOS开发官方文档汇总

    程序员的学习过程是无止境的,程序员学习的途径是多样的.可以从视频教程中领悟,也可以从他人的代码中 理解.但当我们专注于某一个平台在开发的时候,对于某个API使用或者功能实现有疑问,通常简单的测试可以让 ...

  7. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  8. citus 多租户应用开发(来自官方文档)

      citus 官方文档很不错,资料很全,同时包含一个多租户应用的文档,所以运行下,方便学习 环境准备 使用docker-compose 运行,同时集成了graphql 引擎,很方便 docker-c ...

  9. Protocol Buffers官方文档(proto3语言指南)

    本文是对官方文档的翻译,大部分内容都是引用其他一些作者的优质翻译使文章内容更加通俗易懂(自己是直译,读起来有点绕口难理解,本人英文水平有限),参考的文章链接在文章末尾 这篇指南描述如何使用protoc ...

随机推荐

  1. ExtJS 4.2 评分组件

    上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...

  2. .NetCore MVC中的路由(1)路由配置基础

    .NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...

  3. SSH实战 · 用spring框架下的hibernatetemplate的get方法出现的问题

    用get方法查询:      return this.getHibernateTemplate().get(Product.class, pid); 出现错误为:id to load is requi ...

  4. 标准产品+定制开发:专注打造企业OA、智慧政务云平台——山东森普软件,交付率最高的技术型软件公司

    一.公司简介山东森普信息技术有限公司(以下简称森普软件)是一家专门致力于移动互联网产品.企业管理软件定制开发的技术型企业.公司总部设在全国五大软件园之一的济南齐鲁软件园.森普SimPro是由Simpl ...

  5. Web安全相关(三):开放重定向(Open Redirection)

    简介 那些通过请求(如查询字符串和表单数据)指定重定向URL的Web程序可能会被篡改,而把用户重定向到外部的恶意URL.这种篡改就被称为开发重定向攻击.   场景分析 假设有一个正规网站http:// ...

  6. 如何优化coding

    如何优化coding 前言 最近一直在做修改bug工作,修改bug花费时间最多的不是如何解决问题而是怎样快速读懂代码.如果代码写的好的,不用debug就可以一眼看出来哪里出了问题.实际上,我都要deb ...

  7. c#比较两个数组的差异

    将DataTable中某一列数据直接转换成数组进行比较,使用的Linq,要引用命名空间using System.Linq; string[] arrRate = dtRate.AsEnumerable ...

  8. 【Java每日一题】20170105

    20170104问题解析请点击今日问题下方的"[Java每日一题]20170105"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...

  9. Nlog配置实例

      彩色Console target <?xml version="1.0" encoding="utf-8" ?> <nlog xmlns= ...

  10. 快速构建App界面的框架(●'◡'●) -----SalutJs

    前言 卤煮在公司之初接触到的是一个微信APP应用.前端技术采用的是Backbone+zepto等小型JS类库.在项目开发之初,这类中小型的项目采用这两种库可以满足基本的需求.然而,随着迭代的更新和业务 ...