原文地址
Basic Types
在Kotlin中,在通过变量调用成员函数和属性的意义上来讲,任何东西都是对象。一些类型是嵌入的,由于他们的实现被优化了,但是对于用户他们看起来像普通的类。在本章中我们描述多数这种类型:如数字、字符、布尔和数组。
数字:
Kotlin处理数字的方式接近java,但不完全相同。例如,这儿没有对数字隐性扩展转换,并且字面值在某些情况下也不一样。
Kotlin提供如下嵌入类型代表数字(很像java)
Type | Bit width |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
注意在Kotlin中字符不是数字
Literal Constants(字面常量)
下面是几种字面常量对于整数:
- 十进制:123
- 被大写字母L标记的长整形:123L
- 16进制:0x0F
- 二进制:0b00001011
注意:8进制字面值是不支持的。
Kotlin也支持常规的符号对于浮点型:
- Doubles by default(默认Double型): 123.5, 123.5e10
- Floats 被标记为f或者F:123.5f
Underscores in numeric literals (since 1.1)(数字中的下划线)
为了让数字常量更易阅读,你能够使用下划线
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
Representation
在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 = 10000
print(a == a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA == anotherBoxedA) // Prints 'true'
Explicit Conversions(显示转换)
由于不同表示,较小的类型不是较大类型的子类型。如果他们是,我们将在一些情况下有一些问题:
//假定代码,并不实际编译:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // implicit conversion yields a boxed Long (java.lang.Long)
print(a == b) // Surprise! This prints "false" as Long's equals() check for other part to be Long as well
所以不仅一致性,甚至相等性也将会消失。
结果是,较小的类型不会隐式转换为较大的类型。我们不能把一个Byte的值赋给一个Int变量在没有明确的转换的情况下。
val b: Byte = 1 // 成功,字面值被静态的检查
val i: Int = b // ERROR
我们可以使用显示转换去扩大的数字
val i: Int = b.toInt() // OK: explicitly widened
每个数字类型支持如下转换:
• oByte(): Byte
• toShort(): Short
• toInt(): Int
• toLong(): Long
• toFloat(): Float
• toDouble(): Double
• toChar(): Char
隐式转换的缺失很少被注意到因为上下文中的类型推断,和算术操作符被重载为合适的转换,例如:
val l = 1L + 3 // Long + Int => Long
Operations
Kotlin支持被声明为类成员的数字运算的标准集。(但是编译器优化了相关的调用指令),参看操作符重载
作为位运算,这里没有特殊的字符,但是只有能够以前缀方式调用的命名函数,例如:
val x = (1 shl 2) and 0x000FF000
这儿有完整的未操作符(仅仅适用于整型和长整型)
• 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
字符
字符被Char类型表示,他们不能直接被当做数字
fun check(c: Char) {
if (c == 1) { // ERROR: incompatible types
// ...
}
}
字符文字在单引号中’1’.特殊字符能够被转义用反斜杠。如下转义结果被支持:\t, \b, \n, \r, ', ", \ and $.为了编码其他任何字符,适用Unicode转义语法:'\uFF00'
我们可以明确的把一个字符转为一个整型:
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // Explicit conversions to numbers
}
像数字那样,字符被装箱当可空引用类型需要的时候。通过装箱操作,一致性将不被保留。
布尔类型
Boolean类型代表布尔类型,并且有两个值:true和false。
布尔类型被装箱当一个可空的引用被需要的时候。
嵌入操作当布尔类型包括
• || – lazy disjunction
• && – lazy conjunction
• ! - negation
数组
Arrays 在Kotlin中代表有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)创建一个数组array[1,2,3].相反的,arrayofNulls()库函数可以用于创建一个空数组
// Creates an Array<String> with values ["0", "1", "4", "9", "16"]
val asc = Array(5, { i -> (i * i).toString() })
正如我之上所说的那样,[]操作符代表调用成员函数get()和set();
注意:不像java,kotlin中的arrays是不变的。也就意味kotlin不允许我们分配一个Array<String>到Array<Any>,这阻止了一个运行时异常(但是你可以使用Array<out Any>,参看Type Projections)
Kotlin也有一些特殊的类代表没有装箱损耗的原始类型的数组:ByteArray,ShortArray,IntArray等等,这些类没有Array类的相关继承类,但是他们有相同的属性和函数集合。他们中每一个也含有一个相应的工厂函数:
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
字符串
字符串代表类型String。字符串是不可变的。String中的元素是可以被索引操作访问的字符:s[i]。一个字符串可以通过for循环遍历
for (c in str) {
println(c)
}
String 字面值
Kotlin有两种类型的字符串字面值:转义字符串可能含有转义字符,原始字符串可以包含换行和任意文本。一个转义字符串非常像java字符串。
Val s= “Hello,World!\n”
转义是像传统方式那样完成的,通过反斜杠。参看之上的Characters,支持的转义序列列表
一个原始字符串被一个引用(“””)限定,包含非转义和能够包含换行和其他任意字符串。
val text = """
for (c in "foo")
print(c)
"""
你可以移除开头空格通过trimMargin()函数:
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
默认情况下| 用于页边前缀,但是你能够选择另一个字符串并且把它当做参数传入,例如trimMargin(">").
字符串模板
字符串可能包含模板表达式,也就是被评估的代码碎片和结果被嵌入到字符串中。一个模板表达式可以以美元符号开始并且包含一个简单的名称:
val i = 10
val s = "i = $i" // evaluates to "i = 10"
或者一个在花括号中的任意表达式:
val s = "abc"
val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
模板同时被原始字符串和转义字符串支持。如果你需要表示一个字面值$字符在原始字符串中(不支持反斜杠转义),你可以使用如下语法:
val price = """
${'$'}9.99
"""