Boolean型
布尔型只有一个 Boolean 型,用于表示逻辑上的“真”或“假”。与 Java 类似, Kotlin 的 Boolean类型的值只能是true或false,不能用0或者非0来代表。其他数据类型的值也不能转换成 Boolean型。
与前面介绍的数值型、Char类型类似的是,Boolean型的变量不能接受null值,Boolean? 类型的变量才能接受null值。Boolean类型将直接映射为 Java 的 boolean基本类型,但 Boolean? 类型将会映射成 boolean 的包装类: Boolean。
fun main(args: Array<String>) {
var a: Boolean = true
var b = false
var c: Boolean
c = true
println("c的值为${c}")
}
null安全
null安全可以说是Kotiin语言对Java的重大改进之一,这样可以避免 Java编程时令人恐惧的NullPointerException (简称 NPE)
非空类型和可空类型
只有可空类型的变量或常量能接受null值,非空类型的变量或常量不可以。
对于可能发生“值缺失”的情况,编译器会自动推断该变量的类型为可空类型。
Kotlin对可空类型进行了限制 :如果不加任何处理,可空类型不允许直接调用方法、访问属性。因此,通过可空类型与非空类型的区分,KotIin即可在程序中避免空指针异常 。
fun main(args: Array<String>) {
//由于str转换为Int有可能值缺失的情况,故 num1 有可能没有值,所以下面代码是错误的
//var num1: Int = "111". toIntOrNull()
//非空类型可接受空值
var num2: Int? = "111". toIntOrNull()
//编译器推断的类型为 Int?
var num3 = "11".toIntOrNull()
var str: String? = "111"
//可空类型不能直接调用属性或方法,因此下面代码是错误的
//str.length
}
先判断后使用
可空类型的变量不允许直接调用方法或属性,但可以先判断该变量不为 null,然后再调用该变量的方法或属性。
var str: String? = "111"
var len = if (str != null) str.length else -1
println("str的长度为${len}")
str = null
if (str != null && str.length > 0) {
println("str的长度为${str.length}")
} else {
println("str是空字符")
}
}
安全调用
fun main(args: Array<String>) {
var str: String? = "111"
//输出3
println(str?.length)
str = null
//输出null
println(str?.length)
}
上面程序中变量str的类型是 String?,因此程序使用了“?.”安全调用来访问str的length 属性,当b为 null时,程序也不会引发 NPE,而是返回 null。
此外,安全调用还可与 let全局函数结合使用
fun main(args: Array<String>) {
//定义一个元素可为空的数组
val myArr:Array<String?> = arrayOf("ss","111","qwer",null)
for (item in myArr){
//当item不为null是才调用let函数
item?.let { println(it) }
}
}
Elvis运算
Elvis运算也是一种小技巧,其实就是if else的简化写法。对比如下代码:
fun main(args: Array<String>) {
var b:String? = "111"
var len = if(b!=null) b.length else -1
println(len)
b=null
//使用 Elvis 运算符
var len2 = b?.length ?:-1
println(len2)
}
“?:”运算符,该运算符就是 Elvis,它的含义是如果“?:”左边的表达式不为null,则返回左边表式的值,否则返回“?:”右边表达式的值。
由此可见,“?:”其实就是 if分支的简化写法。
强制调用
强制调用是为 NPE“爱好者”准备的,如果读者依然喜欢 Java那种简单、粗暴的方式: 不管变量是否为 null,程序都直接调用该变量的方法或属性。 Kotlin也为这种用法提供了支持 ,用“ !!.”即可强制调用可空变量的方法或属性,这样强制调用可能引发 NPE。例如如下代码:
fun main(args: Array<String>) {
var b:String? = "111"
println(b!!.length)
b=null
//引发空指针异常( NPE)
// println(b!!.length)
//定义一个元素可为空的数组
val myArr:Array<String?> = arrayOf("ss","111","qwer",null)
for (item in myArr){
//引发空指针异常( NPE)
// item!!.let { println(it) }
}
}
字符串
Kotlin使用String代表字符串。字符串表示一个有序的字符集合,例如在前面代码中看到的 ”xq”、 ”sq”等代表字符串,字符串也可被当成多个字符的有序集合。
字符串类型
String类型是一种快速、现代化的字符串实现,字符串中的每一个字符都由独立的 Unicode 字符组成, String 允许通过形如s[i]的格式来访问字符串指定索引处的字符,也可通过for循环遍历字符串中的每一个字符。例如:
fun main(args: Array<String>) {
var b: String = "qwert"
//输出w
println(b[1])
//遍历
for (str in b) {
println(str)
}
}
Kotlin 的字符串有两种字面值( Literal),分别如下。
- 转义字符串: 转义字符串可以有转义字符,转义字符串很像 Java 字符串。
- 原始字符串 :原始字符串可以包含转义字符和任意文本。转义字符不会被转义,原始字符串需要用 3个引号引起来 。
fun main(args: Array<String>) {
//定义普通字符串
var str = "xqsdsd"
println(str.length)
//定义原始字符串
val bet = """
|天上白玉京,
|十二楼五城。
|仙人抚我顶,
|结发受长生。
""".trimMargin()
println(bet)
}
编程时考虑到程序格式,往往会在原始字符串中进行一些缩进, 但这些缩进并不是原始字符希望包含的,此时即可使用的trimMargin()方法来去掉原始字符串前面的缩进,在默认情况下,Kotlin使用竖线(|)作为边界符。也就是说,所有竖线之前的空白内容都会被去掉。如果有必要,开发者也可使用其他字符作为边界符,此时就需要在trimMargin()方法中传入该边界符作为参数。例如:
fun main(args: Array<String>) {
//定义原始字符串
val bet = """
^天上白玉京,
^十二楼五城。
^仙人抚我顶,
^结发受长生。
""".trimMargin("^")
println(bet)
}
字符串模板
Kotlin允许在字符串中嵌入变量或表达式,只要将变量或表达式放入 ${}中即可,这样 Kotlin将会把该变量或表达式的值嵌入该字符串中 。字符串模板不仅可以在普通字符串中使用,也可以在原始字符串中使用。例如:
fun main(args: Array<String>) {
var bookPrice = 79
println("图书的价格是${bookPrice}")
val random = Random()
println("随机数: ${random.nextInt(10)}")
val text = """
|图书的价格${bookPrice}
""".trimMargin()
println(text)
}
Kotlin字符串的方法
Kotlin的String与Java的String 并不是同一个类,因此它们的方法略有不同,但是这两个类所提供的功能大致相似。实际上Kotlin的String 类提供了更多的方法,如提供了一系列 toXxx()方法将字符串转换成数值,首字母大小写以及返回两个字符串相同的前缀、后缀的方法,还有 Java 的 String 的 contains()方法不支持使用正则表达式,但 Kotlin 的 String 的 contains() 方法支持使用正则表达式匹配。
fun main(args: Array<String>) {
//转成数值类型
var bookPrice: String = "79.1"
println("double: ${bookPrice.toDouble()}")
var intValue: String = "79"
println("Int: ${intValue.toInt()}")
var str: String = "dsadsa.com"
//首字母大写
println(str.capitalize())
var str1: String = "DESdsdg.com"
//首字母小写
println(str1.decapitalize())
//返回两个字符串相同的前缀
println(str.commonPrefixWith("dsa.com"))
//返回两个字符串相同的后缀
println(str.commonSuffixWith("dsae.com"))
var str3 = "java8898"
//判断 str3 是否包含 3 个连续的数字
println(str3.contains(Regex("\\d{3}")))
}
类型别名
Kotlin提供了类似于C语言中的 typedef的功能 : 可以为已有的类型指定另一个可读性更强的字。 Kotlin提供了 typealias 来定义类型别名。typealias 语句的语法格式为 :
typealias 类型别名=已有类型
如果类型名太长,我们可以使用较短的新名称来替代原类型名。这样有助于缩短较长的泛型。例如缩短集合类型,为内部类取一个更短的名字:
package test1
import java.io.File
//为 Set<Network . Node>指定更短的别名: NodeSet
typealias StrSet = Set<String>
//为 MutableMap<K, MutableList<File》指定更短的别名: F工leTable<K>
typealias FileTable<K> = MutableMap<K, MutableList<File>>
//为 A.Inner 内部类指定别名
typealias Ainner = A.Inner
//为 B.Inner 内部类指定别名
typealias Binner = B.Inner
fun main(args: Array<String>) {
//使用命名变量
var s: StrSet
var f: FileTable<StrSet>
var a = A().Ainner()
var b = B().Binner()
}
class A {
inner class Inner
}
class B {
inner class Inner
}