在Kotlin语言中,一切皆对象。因此,我们可以调用任意类型变量的属性或方法。比如

1
2
3
4
// {}是一个空的Lamba表达式,我们也可以通过它调用标准库中的also函数
println({}.also {
    print("call function on any variable")
})

基本数据类型

  • numbers
  • booleans
  • characters
  • strings
  • arrays

Numbers

Integer types

  • Byte
  • Short
  • Int
  • Long
1
2
3
4
val oneByte: Byte = 1 // Byte
val oneShort: Short = 1 //Short
val one = 1 // Int
val oneLong = 1L // Long, 后面要接L后缀

Floating-point types

  • Float
  • Double
1
2
val oneDouble = 1.0 // Double,小数默认都是Double类型
val oneFloat= 1.0f // Float, 后面需要跟f后缀(大小写都可以)

字面表示方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 16进制以0x开头 
val hexTen = 0xA
println(hexTen) // 10
// 2进制以0b开头 
val binFour = 0b100 
println(binFour)  // 4

// kotlin不支持8进制

// 可以使用下划线让数据更易读
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

数字在JVM中的表现形式

在JVM平台中,数字都是作为原始数据类型,比如int,double等保存的。

但是可空类型,比如Int? 等则会自动装箱为Java中Integer类型。

因此,一些引用同一个可空类型的变量,可能属于不同的对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a

val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b

// JVM中会优化Int类型的使用,所以在-128~127直接的Int会被重复使用,不再创建
println(boxedA === anotherBoxedA) // true
// 超出范围的每次都会判断是否引用同一个对象
println(boxedB === anotherBoxedB) // false

println(boxedA == anotherBoxedA) // true
println(boxedB == anotherBoxedB) // true

// == 比较两个变量值是否相等
// === 比较两个变量是否引用的相同的对象

数字类型转换

不像Java,Kotlin中的数字类型不会自动转换,无论是从Int转Long,或者Long转Int,都需要显示指定,转换方法如下

  • toByte(): Byte
  • toShort(): Short
  • toInt(): Int
  • toLong(): Long
  • toFloat(): Float
  • toDouble(): Double
  • toChar(): Char

但是大部分时候,都不需要手动指定转换,算术运算符会自动推断类型,比如

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

算术运算符

类似其它语言,Kotlin支持的运算符如下:

  • +
  • -
  • *
  • /
  • %

当然,也可以重载运算符,以实现其它的效果。

除法需要注意的是,使用整型做除法时,返回结果也是整型,小数会被自动去掉

1
2
println(5 / 2) // 2
println( 5 / 2f) // 2.5

位运算符

  • 有符号左移: shl(bits) – signed shift left
  • 有符号右移: shr(bits) – signed shift right
  • 无符号右移:ushr(bits) – unsigned shift right
  • 与操作: and(bits) – bitwise and
  • 或操作:or(bits) – bitwise or
  • 异或操作:xor(bits) – bitwise xor
  • 按位取反: inv() – bitwise inversion
1
2
3
4
5
6
7
8
println( 1 shl 2) // 4
println( -6 shr 1) // -3
println( 6 shr 1) // 3
println( 6 ushr 1) // 3
println( 6 and 4) // 4
println( 6 or 4) // 6
println( 6 xor 4) // 2
println( 6.inv()) // -7

位运算的详细介绍

Unsigned integers

  • UByte: an unsigned 8-bit integer, ranges from 0 to 255
  • UShort: an unsigned 16-bit integer, ranges from 0 to 65535
  • UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1
  • ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1

Booleans

boolean类型只有truefalse两个值

支持的逻辑运算符有:

  • || – disjunction (logical OR)
  • && – conjunction (logical AND)
  • !- negation (logical NOT)

||&& 都是懒惰运算符号。即当返回值能确定时,后面的表达式则不再计算。

比如

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun condition1(): Boolean {
    println("call get condition1")
    return false
}

fun condition2(): Boolean {
    println("call get condition2")
    return true
}

fun main() {
    condition1() && condition2() // 由于condition1返回false, condition2不会再被调用
}

Characters

字符类型,所有的字符类型都是Char类型,可以用单引号来表示,比如: '1'

特殊字符使用\转义,比如\t, \n, \', \", \\, \$

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
val aChar: Char = 'a'

println(aChar)
println('\n') //prints an extra newline character
println('\uFF00')

// 使用digitToInt可以把字符转换成数字
println('5'.digitToInt()) // 5
println('3'.digitToInt(radix = 8)) // 3
println('A'.digitToInt(radix = 16)) // 10
println('k'.digitToInt(radix = 36)) // 20

// radix argument should be in 2..36
// '0'.digitToInt(radix = 1) //  will fail
// '1'.digitToInt(radix = 100) //  will fail
// only 0 and 1 digits are valid for binary numbers
// '5'.digitToInt(radix = 2) //  will fail
// radix = 10 is used by default
// 'A'.digitToInt() //  will fail
// symbol '+' is not a digit in any radix
// '+'.digitToInt() //  will fail
// Only Latin letters are valid for digits greater than 9.
// 'β'.digitToInt(radix = 36) //  will fail

Strings

字符串用双引号""表示

1
2
3
4
5
6
val str = "abcd 123"
// 可以遍历str里的每个Char元素
for (c in str) {
    println(c)
}
println(str[0]) // 'a'

字符串一旦创建之后是不可改变的,所有关于字符串的操作都是返回了一个新的字符串对象,原来的字符串保持不变

1
2
3
val str = "abcd"
println(str.uppercase()) // Create and print a new String object
println(str) // the original string remains the same

使用+操作符号可以拼接字符串

1
2
val s = "abc" + 1
println(s + "def")

Kotlin中字符串有两种形式

  1. 包含转义字符的字符串

    1
    
    val s = "Hello, world!\n"
    
  2. 包含原始字符的字符串(使用三个引号""")

1
2
3
4
val text = """
    for (c in "foo")
        print(c)
"""

可以使用trimMargin()方法来移除开头的边缘符号,默认使用|作为边缘分隔符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
val withoutMargin1 = """ABC
                |123
                |456""".trimMargin()
println(withoutMargin1) // ABC\n123\n456

// 自定义#符号
val withoutMargin2 = """
    #XYZ
    #foo
    #bar
""".trimMargin("#")
println(withoutMargin2) // XYZ\nfoo\nbar

字符串模板

使用$可以在字符串中引用变量

1
2
3
4
5
val i = 10
println("i = $i") // prints "i = 10"

val s = "abc"
println("$s.length is ${s.length}") // prints "abc.length is 3"

Arrays

Kotlin中使用Array类表示数组类型,重载了[]来调用Array类的getset方法,获取数组元素个数可以使用size属性获取

可以使用arryOfarrayOfNulls方法来创建数组, 也可以使用Array类的构造函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
val a = arrayOf(1, 2, 3) //  [1, 2, 3]
// 通过索引访问元素
println(a[1])  // 2
// 通过索引修改元素
a[1] = 4
println(a[1])  // 4
println(a.size) // 3

val b = arrayOfNulls<String>(3) // [null, null, null]

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

Primitive type arrays

Kotlin also has classes that represent arrays of primitive types without boxing overhead: ByteArray, ShortArray, IntArray, and so on. These classes have no inheritance relation to the Array class, but they have the same set of methods and properties. Each of them also has a corresponding factory function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Array of int of size 5 with values [0, 0, 0, 0, 0]
val arr = IntArray(5)

// e.g. initialise the values in the array with a constant
// Array of int of size 5 with values [42, 42, 42, 42, 42]
val arr = IntArray(5) { 42 }

// e.g. initialise the values in the array using a lambda
// Array of int of size 5 with values [0, 1, 2, 3, 4] (values initialised to their index value)
var arr = IntArray(5) { it * 1 }