Kotlin中,所有都是对象是因为我们可以调用任何对象的成员函数和属性。有一些类型是内建的,因为这些类型的实现是优化过的,但是使用的时候看起来和普通类是一样的。本节中我们将介绍这些类型:数据类型,字符类型,布尔类型和数组。(number, character, boolean 和array)
Kotlin中处理数据类型和Java方法很类似,但也不完全一样。例如,没有隐式地扩展数据类型字长,还有写法上也稍有不同。
Kotlin提供下面这些内置的数据类型来表示数字,这和Java很接近。
TypeBit widthDouble64Float32Long64Int32Short16Byte8注意字符类型不在数据类型中。
有如下几种给整数值的字符常量
十进制:123 长整型带L 123L16进制表示:0x0F二进制:0b00001011注意:不支持八进制表示 Kotlin还支持浮点数的表示 - 默认是Double类型 : 123.5, 123.5e10 - Float 类型的要加上标记f或者F:123.5f
可以在比较长的数字中间加上下划线,这样更容易阅读
val oneMillion = 1_000_000 val creditCardNumber = 1234_5678_9012_3456L val socialSecutiryNumber = 999_999_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010在java平台上,数字都是存储成JVM 的基础类型,除非我们需要一个可能为空的数字变量的引用(例如Int?)或者使用了泛型。使用泛型的时候数字被自动封箱。
注意可能为空的自动封箱的数字和原来的数字不保证一致性。
val a: Int = 10000 print(a == a) // Prints 'true' val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA == anotherBoxedA) // !!!Prints 'false'!!!对应的, 非空的封箱,保持一致性。
val a: Int = 1000 print (a == a) // Prints 'true' val boxedA: Int = a val anotherBexedA: Int = a print(boxedA == anotherBoxedA) // Prints 'true'由于不同的表达方式, 值域范围小的类型不是值域范围大的类型的子类型。 Kotlin不支持隐式转换:
val b: Byte = 1 // Ok val i: Int = b // Error可以显式转换:
val b: Byte = 1 val i: int = b.toInt() // OK, 显式的转换每一种数值类型都支持如下转换操作:
toByte(): BytetoShort(): ShorttoInt(): InttoLong(): LongtoFloat(): FloattoDouble(): DoubletoChar(): Char缺少隐式转换很难被发现,因为类型是根据上下文推断的,并且算数操作符都被重载成适合改转换的。
val longNumber = 1L + 3 // Long + Int >= Longkotlin支持标准的算数操作符,他们被定义成对应类的成员函数。编译器会把对应的函数调用优化成对应的指令。 详见 Operator overlading。
对于比特位的操作,没有定义特殊字符给这些运算符,只是用可以被内置的方式来命名这些函数。例如
val x = (1 shl 2) and 0x0000_FF00下面是支持全部的比特操作(仅对Int 和Long 类型支持)
shl(bits) -带符号左移位,相当于(Java 的<<)shr(bits) -带符号右移位,相当于(Java的>>)ushl(bits) -不带符号左移位,相当于(Java 的<<<)ushr(bits) -不带符号右移位,相当于(Java 的>>>)and(bits) -按位与, 相当于(Java 的&)or(bits) -按位或, 相当于(Java 的|)xor(bits) -按位异或, 相当于(Java 的^)inv() -按位取反, 相当于(Java 的~)Kotlin中字符是用Char来表示。 他们不直接被当做数值来用
fun check(c: Char) { if (c == 1) { // Error, incompatible types } }字符是用单引号括起来的字符表示:'1' 特殊字符可以是用反斜杠来转义。这些转义的特殊字符是支持的\t,\b,\n,\r,\',\",\\和\$。 要编码其他字符,需要使用Unicode转移语法:\uFF00
可以显式地把一个字符转换成Int类型数值
fun decimalDigitValue(c: Char): Int { if (c !in '0'..'9') throw IllegalArgumentException("Out of range"); return c.toInt() - '0'.toInt() }和数值一样,可以为空的引用会触发自动封箱。 这种情况下,不保证一致性。
布尔类型用Boolean来表示,有两个值true 和false 布尔类型在需要一个可以为空的引用时,也会自动封箱。 布尔类型内置的操作符包括:
|| 或&& 与! 非数组类型使用Array 来表示,有get 和set 函数(重载转换成[]),size 属性,和其他一些有用的函数
class Array<T> private constructor() { val size: Int operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> // .. }创建一个数组,我们可以使用库函数arrayOf(), 例如arrayOf(1, 2, 3)会创建数组[1, 2, 3]。 还可以使用库函数arrayOfNulls()来创建一个指定大小的空数组 还可以使用一个工厂函数,包含数组大小和一个可以根据坐标返回每个元素初始值的函数:
// 创建一个Array<String> ["0", "1", "4", "9", "16"] val asc = Array(5, { i -> (i * i).toString() }可以用[] 来访问数组,相当于调用了get() 和set()
注意:和Java中的数组不同,Kotlin中的数组是不可变的。这意味着在Kotlin中不允许我们把一个Array<String> 赋值给一个Array<Any>, 这样可以防止可能的运行时错误。(但是可以使用Array<outAny>, 详见Type Projections)
Kotin 还有定制的类来表示基础数据类型的数组来避免封箱带来的额外的开销,他们包括ByteArray, ShortArray, IntArray 等等。 这些类和Array 没有继承关系,但是他们有同样的函数接口和属性接口。每一个都有对应的工厂方法。
val x: IntArray = intArrayOf(1, 2, 3) x[0] = x[1] + x[2]字符串是用Strings这个类来表示的。 字符串是不可变的。字符串的单个字符可以通过坐标操作来访问:s[i]。一个字符串可以通过一个for循环来遍历。
for (c in str) { println(c) }Kotlin有两种字符串语法。转义字符串,可能包含有已经转义的字符;元字符串,包含换行和强制文字。 转义字符串和Java的字符串非常接近
val s = "Hello, world!\n"转义方式和传统转义一样使用反斜线。
元字符串是用三个引号""" ,不包括任何转义,可以包含换行和任意其他字符。
val text = """ for (c in "foo") print(c) """可以通过trimMargin() 方法来去掉每行前面的空格
val text = val text = """ |Tell me and I forget. |Teach me and I remember. |Involve me and I learn. |(Benjamin Franklin) """ val trimed = text.trimMargin() println($trimed)输出是
Tell me and I forget. Teach me and I remember. Involve me and I learn. (Benjamin Franklin)默认参数是| 也可以使用其他字符。
字符串可以包含字符串模板表达式,例如代码可以判断哪些字符要被输出到字符串结果。一个模板表达式是用美元符开始$,包含一个简单变量名
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 """