1.基本类型
数字Number
kotlin中数字与java类型,但是也有所区别,比如数据不能自动展开(int 数字可以作为long使用),字面值有时候也不太一样,另外字符不是数字。
kotlin中数字类型如下,与java基本一致
类型 | 宽度 |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
数字字面值
常见数字字面值如下:
- 十进制:如123,可以在后面添加大写L代表Long类型,如123L
- 十六进制:如0x0f
- 二进制:如0b00111100
- 八进制:kotlin不支持
- Double类型:如123.5,123.5e10
- Float类型:后面添加f或者F,如123.45f
自kotlin 1.1开始,数字字面值中可以添加下划线增强可读性,比如
var bytes = 0b11001100_00100100_10010011
Representation
数字可以通过对象引用或者泛型实现自动装箱,注意数字装箱后与原数字是相等的,但是同一个数字的多个装箱后对象不一定相等
var a:Int = 100
print(a === 100) // true
var boxedA:Int? = a
var anotherBoxedA:Int? = a
print(boxedA === anotherBoxedA) // 结果不可靠
显式转换
较小类型不会自动转换为较大类型,比如我们将Byte转换为Int需要显式转换
var b:Byte = 1
var i:Int = b.toInt()
每个数据类型支持如下的显式转换方法:
- toByte()
- toShort()
- toInt()
- toLong()
- toFloat()
- toDouble()
- toChar()
在算术运算中存在隐式转换,如
var i = 1L + 2
操作符
kotlin支持标准的数字运算。 位运算有相应的方法,通常使用括号括起来。比如以下是完整的位运算操作符var x = (1 shl 2) and 0x000ff000
- shl:带符号左移(类似java中的<<)
- shr:带符号右移(类似java中的>>)
- ushr:无符号右移(类似java中的>>>)
- and
- or
- xor
- inv()
Float类型比较
针对Float类型的数据比较主要有三种操作
- 相等性比较: a == b
- 比较操作符比较: a > b
- 范围的创建和检查: a..b x in a..b
通常,在操作数都是Float和Double类型时,以上操作都是遵循ieee 754标准的。
然而,有些时候操作数并不确定类型,比如Any,Comparable<..>,以上的操作会使用Float和Double类的equals和compareTo方法来判断,有些地方与标准不太符合,比如
- NaN与它自身相等
- NaN大于其它所有特殊符号(element),比如无穷大
- -0.0小于0.0
字符Character
由Char类修饰,注意与java不同的是,kotlin中Char不可以作为数字使用
Char字面值的表示与java基本一致,常见为三种,1为单引号括起来,2为转义字符,3为unicode字符,分别如下
'a'
\t
'\uFF00'
调用toInt可以将Char转化为数字,如
‘1’.toInt()
Boolean
与:&&
或:||
非:!
集合Array
可以使用库函数arrayOf构造Array,如
arrayOf(1, 2, 3)
也可以使用带size和生成每个元素的function的工厂方法来构造,如
val asc = Array(5, {i -> (i*i).toString() } )
针对基础类型的array,kotlin提供了对应的构造类和构造方法,比如ByteArray,IntArray等。
var x: IntArray = intArrayOf(1, 2, 3) //构造集合的方法
String
字符串由类String来描述,其元素为Char,可以通过index来访问,也可以通过for循环来遍历
var s = “Hello”
var c = s[2]
for (c in s) {
println(c)
}
字符串字面值
字符串字面值有两种,转义字符串与原始字符串
转义字符串和java中字符串类似,其中带有转义字符,如
var str = “Hello, world!\n”
原始字符串由三引号括起来,其中不包含转义字符,可以包含换行或者其他字符,同时可以使用trimMargin函数移除每行前面的空白leading whitespace,默认|标记行首
var text = """
|This is the first line.
|This is the second line.
""".trimMargin()
字符串模板
在字符串模板中,一段代码可以先计算出值然后拼接到字符串中,有两种方式,一种为$字符后跟变量名,如
var i = 10
var str = “i=$i”
另一种方式为$后添加大括号,大括号中可以是任意表达式
var s = “abc”
var str = “ s.lengthis {s.length}”
2.包package
import包名可有可无
import语句可以用来导入类,顶层function和properties,enum常量,针对import后名称有重复的,可以采用as语句调整本地名称,比如
import abc.Aclass as Bclass
3.流程控制
if
和java中类似,可以作为语句,也可以作为表达式,当作为表达式的时候用于直接返回数据,而且需要有else关键字
var result = if (a > b) a else b
when
类似C语言当中的switch语句,顺序匹配各个条件,直到匹配或者到达else,其中条件不一定是常量,可以是判断语句,比如
when(x) {
in 1..10 -> println(“x in range of 0 to 10”)
is String -> println(“x is String”)
else -> println(“else”)
}
如果期望多个条件condition执行同一个语句,只需要将condition用,分隔即可。
when语句可以用作表达式,比如
fun hasPrefix(x: Any) = when(x) {
is String -> x.startWith(“prefix”)
else-> false
}
当when不带参数时,类似普通的if else语句,会执行首次condition满足的语句。
for循环
for语句用于循环迭代数据, 其格式如下
for (item in collection) println(item)
后面通常接语句块。
遍历集合的同时访问index
for (i in array.indices) {
print(array[i])
}
while循环
while和do while与java类似
while(condition) {
statement
}
do {
statement
} while(condition)
4.跳转
三个关键字,return break 和continue,与java使用基本一致,return针对function,break和continue针对循环,默认均为跳出最内层的function或者loop。
语句前面可以添加label,用于定位,语法为label后面紧跟@字符。使用lable可以改变return break continue的默认行为。
// 当j为10时会跳转到外层循环,使用continue类似。
abc@ for(i in 1..100) {
for (j in 1..100) {
if (j == 10) break@abc
}
}
在使用return 时,如果有嵌套function,如果内部function为lambda表达式,则return 到外部funtion。想要跳转到内部function有三种方式,第一种为给lambda表达式添加label,并return到label,比如
fun foo() {
ints.forEach lit@{
if (it == 0) return@lit //跳转到lit,而不是foo
println(it)
}
}
第二种为跳转到隐式label,上面例子中lambda表达式所在函数存在隐式label,即forEach,所以可以这样写
fun foo() {
ints.forEach {
if (it == 0) return@forEach //跳转到forEach,而不是foo
println(it)
}
}
第三种方式为将lambda表达式调整为匿名function,此时return默认跳转出内部的匿名function
fun foo() {
ints.forEach (fun(value: Int){
if (value == 0) return //跳出匿名function
println(value)
})
}
如果希望添加label的同时有返回值,只需要与正常一样写即可
return@lit 1