kotlin中文站很多都做了讲解,以下只是在学习过程中的记录,更详细可进入kotlin中文网
定义函数
使用fun 关键字声明
-
带有两个 Int 参数、返回 Int 的函数
fun sum(a: Int, b: Int): Int { return a + b }
-
将表达式作为函数体、返回值类型自动推断的函数
fun sum(a: Int, b: Int) = a + b
-
函数返回无意义的值"Unit"(java是“void”)
fun printSum(a: Int, b: Int): Unit { println("sum of $a and $b is ${a + b}") }
-
Unit 返回类型可以省略
fun printSum(a: Int, b: Int) { println("sum of $a and $b is ${a + b}") }
函数用法
1. 传统方法
val result = sum(1,2)
2. 成员函数的类调用
Sample().foo() // 创建类 Sample 实例并调用 foo
1.参数
函数参数使用 Pascal 表示法定义,即 name: type。参数用逗号隔开。每个参数必须有显式类型
2.默认参数
函数参数可以有默认值,当省略相应的参数时使用默认值。与其他语言相比,这可以减少重载数量
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { …… }
默认值通过类型后面的 = 及给出的值来定义
注:当覆盖一个带有默认参数值的方法时,必须从签名中省略默认参数值
open class A {
open fun foo(i: Int = 10) { …… }
}
//继承类
class B : A() {
override fun foo(i: Int) { …… } // 不能有默认值
}
如果一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用命名参数调用该函数来使用
fun foo(bar: Int = 0, baz: Int) { …… }
foo(baz = 1) // 使用默认值 bar = 0
如果在默认参数之后的最后一个参数是 lambda 表达式,那么它既可以作为命名参数在括号内传入,也可以在括号外传入
fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { …… }
foo(1) { println("hello") } // 使用默认值 baz = 1
foo(qux = { println("hello") }) // 使用两个默认值 bar = 0 与 baz = 1
foo { println("hello") } // 使用两个默认值 bar = 0 与 baz = 1
3.命名参数
可以在调用函数时使用命名的函数参数。当一个函数有大量的参数或默认参数时这会非常方便。
给定以下函数:
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
……
}
1.默认参数调用
reformat(str)
2.非默认参数调用
reformat(str, true, true, false, '_')
3.省略类型
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
4.只需要两个参数的调用
reformat(str, wordSeparator = '_')
5.当一个函数调用混用位置参数与命名参数时,所有位置参数都要放在第一个命名参数之前。例如,
允许调用 f(1, y = 2) 但不允许 f(x = 1, 2)。
6.可以通过使用星号操作符将可变数量参数(vararg) 以命名形式传入:
fun foo(vararg strings: String) { …… }
foo(strings = *arrayOf("a", "b", "c"))
注:在调用 Java 函数时不能使用命名参数语法,因为 Java 字节码并不总是保留函数参数的名称
返回 Unit 的函数
如果一个函数不返回任何有用的值,它的返回类型是 Unit。 Unit 是一种只有一个值——Unit 的类型。 这个值不需要显式返回:
fun printHello(name: String?): Unit {...}
fun printHello(name: String?) { …… }
单表达式函数
1.当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可
fun double(x: Int): Int = x * 2
2.当返回值类型可由编译器推断时,显式声明返回类型是可选的
fun double(x: Int) = x * 2
显式返回类型
具有块代码体的函数必须始终显式指定返回类型,除非他们旨在返回 Unit,在这种情况下它是可选的。 Kotlin 不推断具有块代码体的函数的返回类型,因为这样的函数在代码体中可能有复杂的控制流,并且返回类型对于读者(有时甚至对于编译器)是不明显的。
可变数量的参数
函数的参数(通常是最后一个)可以用 vararg 修饰符标记
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}
//允许将可变数量的参数传递给函数
val list = asList(1, 2, 3)
只有一个参数可以标注为 vararg 如果 vararg 参数不是列表中的最后一个参数, 可以使用命名参数语法传递其后的参数的值,或者,如果参数具有函数类型,则通过在括号外部传一个 lambda。
当我们调用 vararg-函数时,我们可以一个接一个地传参,例如 asList(1, 2, 3),或者,如果我们已经有一个数组并希望将其内容传给该函数,我们使用伸展(spread)操作符(在数组前面加 *):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
中缀表示法
lambda 表达式
lambda 表达式本质上是一个函数,虽然它不属于某个特定的类,但具备参数列表、函数主体、返回类型,甚至能够抛出异常;其次它是匿名的,lambda 表达式没有具体的函数名称;lambda 表达式可以像参数一样进行传递,从而简化代码的编写
参数列表 -> 表达式
参数列表 -> {表达式集合}
需要注意 lambda 表达式隐含了 return 关键字,所以在单个的表达式中,我们无需显式的写 return 关键字,但是当表达式是一个语句集合的时候则需要显式添加 return 关键字,并用花括号{ } 将多个表达式包围起来
//1.返回给定字符串长度(隐含return)
(String s)-> s.length()
//2.始终返回2的无参函数(隐含return)
() -> 2
//3.含多行表达式,需要用花括号括起来,并显示添加return
(int x,int y)->{
int z = x * y;
return x+z;
}
基于函数式接口使用 lambda 表达式 函数式接口:函数式接口定义为仅含有一个抽象方法的接口
public interface apple{
boolean istrue(Apple apple);
}
lambda 表达式的使用需要借助于 函数式接口,也就是说只有函数式接口出现地方,我们才可以将其用 lambda 表达式进行简化
public class Java8Tester {
public static void main(String args[]) {
final int num = 1;
//lambda表达式
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2); // 输出结果为 3
}
//函数式接口
public interface Converter<T1, T2> {
void convert(int i);
}
}
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
loop和Range
开区间与闭区间
Range开区间用(a,b)来表示
闭区间用[a,b]来表示
闭区间包括两端点a和b,而开区间不包含两端的a和b
1..100表示闭区间,包含1和100
1 util 100表示开区间,不包含1和100
//区间方法
fun range(sum: IntRange){
for (num in sum){
println("打印的数字为:${num}")
}
}
//闭区间调用
range(1 .. 100)
//开区间调用
range(1 until 100)
//reversed转换数据位置
var sum = sum.reversed()
step:步长
for (num in sum step 3){
println("打印的数字为:${num}")
}
//打印出的数据为步长打印,3,6,9...
sealed class 密封类
sealed class Son {
fun sayHello(say:String){
println("说了什么$say")
}
class boy : Son()
class girl : Son()
}
//调用
var boy:Son = Son.boy()
boy.sayHello("boy")
var gril:Son = Son.girl()
gril.sayHello("gril")