1.函数
函数声明如下:
fun 函数名称([函数参数...]): 返回值类型{
// 方法体
}
fun sum(num1: Int, num2: Int): Int {
return num1 + num2
}
注意:Kotlin函数返回值为空时为Unit
,并非常见的void
函数可以设置默认值:
fun printNum(numA: Int = 10, numB: Int = 20): Int{
println(numA + numB)
}
函数入参默认为val(常量),不支持在方法体中修改
1.1 常用的库函数
println:输出一行
readln:接收一行
pow:取次方
1.2 高阶函数
一个函数如果入参类型 or 返回值类型是函数,那么这个函数就是一个高阶函数
一个变量可以有各种各样的类型(Int/String/…),函数当然也会有自己的类型
对于下面的函数,(String) -> Int
就是该函数的类型。函数类型其实就是将函数的入参和返回值抽象出来。
fun test(str: (String)): Int {
return str.toInt()
}
1.2.1 变量接收函数(声明)
Kotlin支持将函数赋给一个变量,与Java不同的是格式上有所区别
// func1为一个能够表示函数的变量,该函数接收一个Int作为入参,没有返回值
var func1: (Int) -> Unit
既然Kotlin已经能够使用变量接收函数了,那么必然就能使用函数A作为函数B的形参
// test作为一个函数,能够接受另一个函数的返回值作为入参
// 形参函数的入参事String,返回值是一个Int
fun test(num1: (String) -> Int) {
}
1.2.2 变量接收函数(赋值)
对于已有函数,可以使用::
获取函数引用
fun main() {
var func: (String) -> Int = ::test
println(func("1"))
}
fun test(str: (String)): Int {
return str.toInt()
}
也可以直接写匿名函数:
fun main() {
var func: (String) -> Int = fun(str: String): Int {
return str.toInt()
}
}
匿名函数还有一种更简洁的写法(项目中绝大多数采用这种Lambda表达式来调用高阶函数):
fun main() {
var func: (String, String) -> Unit = { str1: String, str2: String ->
println(str1 + str2)
}
func("a", "1")
}
// 输出
a1
因为Kotlin有匿名推断机制,所以lambda入参类型可以去掉
fun main() {
var func: (String, String) -> Unit = { str1, str2 ->
println(str1 + str2)
}
func("a", "1")
}
在lambda表达式只有一个入参的情况时,无需显式写明入参,在函数体内可以直接使用it
来代替入参
val func1: (Int) -> Unit = {println(it)}
1.4 内联函数
类似于C++,Kotlin使用inline
声明一个内联函数。内联函数在编译时会被编译器直接替换到调用该方法的地方
fun main() {
test()
}
inline fun test() {
println("111")
}
// 内联函数替换后
fun main() {
println("111")
}
2.对象
2.1 主构造函数
一个类可以有多个构造函数,直接写在类名后的是主构造函数。这种形式可以写上默认值,也可以不写
class Student constructor(var name: String, var age: Int) {
}
也可以将类属性放在类体中,类似于Java,但是这种形式要求必须写上默认值
class Student () {
var name: String = ""
var age: Int = 0
}
还有一种形式是以上两种形式结合起来,下面这种方法能够自定义getter和setter
class Student (name: String, age: Int) {
var name: String = name
get() = field
set(value) {
field = value + "1"
}
var age: Int = age
get() = field
set(value) {
field = value * 10
}
}
和Java一样,如果没有规定主构造函数,那么Kotlin会为当前类生成一个无参的默认构造函数;如果规定了主构造函数,那么就不会再有默认的无参构造函数
2.2 次要构造函数
次要构造函数还是需要使用this()
来调用主构造函数。次要构造函数可以有自己的函数体
class Student (var name: String, var age: Int) {
constructor(name: String): this(name, 0) {
// 次要构造函数体
}
}
2.3 对象的初始化
因为主构造函数没有函数体,想在对象初始化阶段进行操作时,可以使用init块
class Student (var name: String, var age: Int) {
init {
println(name + "出生了")
}
}
2.4 初始化顺序
当执行一个对象的构造函数时,对应的初始化顺序如下:
- init代码块
- 主构造函数(如果没有会执行默认的无参构造函数)
- 次要构造函数
2.5 空值和空类型
Kotlin默认所有的类型都是非空类型,即编译阶段就可以避免出现变量被赋值为null的情况出现
如果真的需要将某个变量在初始化情况下使用null而不是某个具体的对象,需要在类型名称后加一个?
将该变量声明为可空类型
fun main() {
val student: String? = null
}
Kotlin提供了一种安全的空类型操作:如果想要安全地访问可能包含null值的对象的属性,可以使用安全调用运算符?.
如果对象属性为null则返回null
如果想在可空变量实际为null时返回一个指定的结果,可以使用?:
fun main() {
var student: Student? = null
var studentName: String = student?.name ?: "name"
println(studentName)
}
2.6 访问控制权限
Kotlin有4种访问控制权限:public/internal/protected/private
其中internal是Java所没有的。如果使用了internal修饰符,他将在当前的项目中可以随意访问,权限等同于public,但是如果别人引用我们的项目,别人无法使用被修饰的东西