属性与变量
Kotlin 类中的属性,既可以使用关键字 var 声明为可变的,也可以用 val 声明为只能赋值一次的只读变量。
变量
/**
*只读变量
*/
val a: Int = 1 //立即赋值
val b = 30 //自动推断出 Int 类型
val c = "hello" //自动推断出 String 类型
/**
*可变变量
*/
var name: String = "keven" //立即赋值
var age: Int = 18 //立即赋值
var address: String = "北京" //立即赋值
类
Kotlin 中使用关键字 class 声明类
class Person {
}
构造函数
在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后。
class Person constructor(firstName: String) {
}
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。
class Person(firstName: String) {
}
也可以在类中定义次构造函数
class Person {
//定义一些可变变量
var name: String = "keven"
var age: Int = 18
var address: String = "北京"
//定义带参数构造函数
constructor(name: String, age: Int, address: String) {
this.name = name
this.age = age
this.address = address
}
//无参构造函数
constructor()
}
使用 Person 类
//Kotlin 中没有 new 关键字
var result = Person() //使用无参构造函数
result.name = "KEVEN" //给变量赋值
result.age = 19
result.address = "上海"
//使用有参构造函数
var person=Person("Keven",20,"深圳")
函数
Kotlin 中的函数使用 fun 关键字声明
1. 定义带参函数
注意:如果一个函数不返回任何有用的值,它的返回类型是 Unit。Unit 是一种只有一个值 Unit 的类型。这个值不需要显式返回
//带有两个 Int 参数
//$a $b $c 代表引用 a、b、c 的值
fun printSum(a: Int, b: Int) {
var c=a+b
println("sum of $a and $b is $c")
}
2. 定义带参数、带返回值的函数
//带有两个 Int 类型参数,返回值为 Int 类型
fun Sum(a: Int, b: Int): Int {
return a + b
}
3.单表达式函数
将表达式作为函数体,返回值类型自动推断的函数
fun sum(a: Int, b: Int) = a + b
4. 定义参数有默认值的函数
//其中 Boolean 类型参数 isMale 默认值为 true
//其中 Char 类型参数 short 默认值为 'a'
fun reformat(name: String, isMale: Boolean = true, short: Char = 'a') {
}
//调用有默认值参数的函数时,可不传有默认值的参数
reformat("CUE")
//当然也可以全传递
reformat("CUE",true,'C')
5. 可变数量参数的函数
函数的参数(通常是最后一个)可以用 vararg 修饰符标记
//使用 vararg 进行参数修饰
fun asList(vararg list: Int) {
for (a in list)
println("a = $a")
}
对于可变参数函数进行调用
//传入任意个数 Int 类型参数
asList(1, 2, 3, 4)
asList(0, 1, 2)
字符串模板
字符串可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
val i = 10
println("i = $i") // 输出“i = 10”
或者用花括号括起来的任意表达式:
val s = "abc"
println("$s.length is ${s.length}") // 输出“abc.length is 3”
原始字符串与转义字符串内部都支持模板。 如果你需要在原始字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:
val price = """${'$'}9.99"""
println(price)//输出“$9.99”
if 表达式
在 Kotlin 中,if 是一个表达式,即它会返回一个值。 因此就不需要三元运算符(条件 ? 然后 : 否则),因为普通的 if 就能胜任这个角色。
// 传统用法
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// 作为表达式
val max = if (a > b) a else b
if 的分支可以是代码块,最后的表达式作为该块的值
//输出 a、b 中较大的一项
var a = 1
var b = 2
val max = if (a > b) {
a
} else {
b
}
使用可空值及 null 检测
许多编程语言(包括 Java)中最常见的陷阱之一,就是访问空引用的成员会导致空引用异常。在 Java 中,这等同于 NullPointerException 或简称 NPE。
Kotlin 的类型系统旨在从我们的代码中消除 NullPointerException。
使用
在 Kotlin 中,类型系统区分一个引用可以容纳 null (可空引用)还是不能容纳(非空引用)。 例如,String 类型的常规变量不能容纳 null:
var a: String = "abc"
a = null // 编译错误
如果要允许为空,我们可以声明一个变量为可空字符串,写作 String?:
var b: String? = "abc"
b = null // ok
print(b)
检测
val b: String? = "Kotlin"
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
这只适用于 b 是不可变的情况(即在检查和使用之间没有修改过的局部变量 ,或者不可覆盖并且有幕后字段的 val 成员),因为否则可能会发生在检查之后 b 又变为 null 的情况。
安全的调用
安全调用操作符,写作 ?.:
val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // 无需安全调用
如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 Int?。
安全调用在链式调用中很有用。例如,如果一个员工 Bob 可能会(或者不会)分配给一个部门, 并且可能有另外一个员工是该部门的负责人,那么获取 Bob 所在部门负责人(如果有的话)的名字,我们写作:
bob?.department?.head?.name
如果任意一个属性(环节)为空,这个链式调用就会返回 null。
如果要只对非空值执行某个操作,安全调用操作符可以与 let 一起使用:
val listWithNulls: List = listOf("Kotlin", null)
for (item in listWithNulls) {
item?.let { println(it) } // 输出 Kotlin 并忽略 null
}
安全调用也可以出现在赋值的左侧。这样,如果调用链中的任何一个接收者为空都会跳过赋值,而右侧的表达式根本不会求值:
// 如果 `person` 或者 `person.department` 其中之一为空,都不会调用该函数:
person?.department?.head = managersPool.getManager()
Elvis 操作符
判断如果 b 不为 null ,返回 b 的长度,否则返回 -1
val l: Int = if (b != null) b.length else -1
除了完整的 if-表达式,这还可以通过 Elvis 操作符表达,写作 ?:
val l = b?.length ?: -1
如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。
请注意,因为 throw 和 return 在 Kotlin 中都是表达式,所以它们也可以用在 elvis 操作符右侧。这可能会非常方便,例如,检查函数参数:
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ……
}
安全的类型转换
如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException。 另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null
val aInt: Int? = a as? Int
可空类型的集合
如果你有一个可空类型元素的集合,并且想要过滤非空元素,你可以使用 filterNotNull 来实现
val nullableList: List = listOf(1, 2, null, 4)
val intList: List = nullableList.filterNotNull()
本小节就介绍到这里,下一小节我们会继续学习 Kotlin 的基本语法。