Kotlin 进阶之路 目录
常量
- val = value,值类型
- 类似Java的final
- 不可能重复赋值
- 运行时常量:val x =getX()
- 编译期常量:const val x = 2
变量
- val = variable
- var x = "HelloWorld"//定义变量
- x = "Hello,China"//再次赋值
类型推导
- 编译器可以推导量的类型
- val string ="Hello" //推导出String类型
- val int = 5 //Int 类型
- var x = getString() + 5 //String类型
函数
- 以特定功能组织起来的代码块
- fun[函数名]([参数列表]):[返回值类型]{[函数体]}
- fun[函数名]([参数列表]) = [表达式]
举例:
- fun sayHi(name:String) { println("Hi,$name") }
- fun sayHi(name:String) = println("Hi,$name")
匿名函数
- fun([参数列表])...
- val sayHi = fun(name:String) = println("Hi,$name")
编写函数的注意事项
- 功能单一
- 函数名要做到顾名思议
- 参数个数不要太多
Lambda 表达式
- 匿名函数
- 写法:{[参数列表]->[函数体,最后一行是返回值]}
- val sum = {a:Int,b:Int->a + b }
Lambda的类型举例
- ()->Unit
无参,返回值为Unit
- (Int)->Int
传入整型,返回一个整型
- (String,(String)->String)->Boolean
- 传入字符串、Lambda表达式,返回Boolean
Lambda表达式的调用
- 用()进行调用
- 等价于invoke()
- val sum = {a:Int,b:Int -> a + b}
- sum(2,3)
- sum.invoke(2,3)
Lambda表达式的简化
- 函数参数调用时最后一个Lambda可以移出去
- 函数参数只有一个Lambda,调用时小括号可以省略
- Lambda只有一个参数可默认为it
- 入参,返回值与形参一致的函数可以用函数引用的方式作为实参传入
fun main(args: Array) {
println(int2Long(3))
println(sum(2, 3))
println(sum2(5, 6))
println(sum.invoke(1, 3))
val args: Array = arrayOf(1, 2, 3, 4, 5, 6)
for (i in args) {
println(i)
}
args.forEach(::println)
println("--------------------------------")
args.forEach ForEach@{
if (it == 2) return@ForEach
println(it)
}
println("The End 1.....")
args.forEach {
if (it == 3) return
println(it)
}
println("The End 2.....")
}
val int2Long = fun(x: Int): Long {
return x.toLong()
}
val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }
val sum2 = { arg1: Int, arg2: Int -> println("$arg1 + $arg2 = ${arg1 + arg2}") }
3
5
5 + 6 = 11
kotlin.Unit
4
1
2
3
4
5
6
1
2
3
4
5
6
--------------------------------
1
3
4
5
6
The End 1.....
1
2
类成员
- 属性:作者说成员变量,类范围内的变量
- 方法:或者说成员函数,类范围内的函数
函数和方法的区别
- 函数强调功能本身,不考虑从属
- 方法的称呼通常是从类的角度出发
- 叫法不同而已,不要纠结
定义属性
- 构造方法参数中val/var修饰的都是属性
- 类内部也可以定义属性
属性访问控制
- 属性可以定义getter/setter
- val a:Int = 0 //不能定义set()
- get() = field
- var b:Float = 0f //可以定义getter/setter
- set(value){field = value}
属性初始化
- 属性的初始化尽量在构造方法中完成
- 无法在构造方法中初始化,尝试降级为局部变量
- var用lateinit延迟初始化,val用lazy
- 可空类型谨慎用null直接初始化
class X
//lateinit 延迟初始化
class A {
var b = 0
lateinit var c: String
lateinit var d: X
val e: X by lazy {
println("init X")
X()
}
//可空类型谨慎用null直接初始化
var cc: String? = null
}
fun main(args: Array) {
println("start")
val a = A()
println("init a")
println(a.b)
println(a.e)
a.d = X()
println(a.d)
println(a.cc?.length)
}
start
init a
0
init X
chapter3.X@7106e68e
chapter3.X@7eda2dbb
null
基本运算符
- 任何类可以定义或者重载父类的基本运算符
- 通过运算符对应的具体函数来定义
- 对参数个数作要求,对参数和返回值类型不作要求
- 不能像Scale一样定义任意运算符
中缀表达式
- 只有一个参数,且用infix修饰的函数
- class Book{ infix fun on(place:String){...}}
- Book() on "My Desk"
分支表达式
- if...else
- if(a ==b ) ... else if(a == c) ... else ...
- 表达式与完备性
- val x = if(b < 0) 0 else b
- val x = if(b < 0) 0 //错误,赋值时,分支必须完备
private const val USERNAME = "kotlin"
private const val PASSWORD = "jetbrains"
private const val ADMIN_USER = "admin"
private const val ADMIN_PASSWORD = "admin"
private const val DEBUG = 1
private const val USER = 0
fun main(args: Array) {
//1.变量赋值
// var mode = USER
// if (args.isNotEmpty() && args[0] == "1") {
// mode = DEBUG
// }
//2. 表达式给变量赋值
val mode = if (args.isNotEmpty() && args[0] == "1") {
DEBUG
} else {
USER
}
println("请输入用户名:")
val username = readLine()
println("请输入密码:")
val password = readLine()
if (mode == DEBUG && username == ADMIN_USER && password == ADMIN_PASSWORD) {
println("管理员登录成功")
} else if (username == USERNAME && password == PASSWORD) {
println("登录成功")
} else {
println("登录失败")
}
When 表达式
- 加强版switch,支持任意类型
- 支持纯表达式条件分支(类似if)
- 表达式与完备性
fun main(args: Array) {
val x = 5
when (x) {
is Int -> println("Hello $x")
in 1..100 -> println("$x is in 1..100")
!in 1..100 -> println("$x is not in 1..100")
args[0].toInt() -> println("$x == args[0]")
}
}
Hello 5
循环语句
for循环
- 基本写法
- for(element in elements)...
- 给任意类实现Iterator方法
fun main(args: Array) {
val args: Array = arrayOf('a', 'b', 'c', 'd')
for (arg in args) {
println(arg)
}
println("-------------------------------")
for ((index, value) in args.withIndex()) {
println("$index -> $value")
}
println("-------------------------------")
for (indexedValue in args.withIndex()) {
println("${indexedValue.index} -> ${indexedValue.value}")
}
println("-------------------------------")
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
for (i in list) {
println(i)
}
}
class MyIterator(val iterator: Iterator) {
operator fun next(): Int {
return iterator.next()
}
operator fun hasNext(): Boolean {
return iterator.hasNext()
}
}
class MyIntList {
private val list = ArrayList()
fun add(int: Int) {
list.add(int)
}
fun remove(int: Int) {
list.remove(int)
}
operator fun iterator(): MyIterator {
return MyIterator(list.iterator())
}
}
a
b
c
d
-------------------------------
0 -> a
1 -> b
2 -> c
3 -> d
-------------------------------
0 -> a
1 -> b
2 -> c
3 -> d
-------------------------------
1
2
3
While循环
类似于C语言
跳过和终止循环
- 跳过当前循环用continue
- 终止循环用break
- 多层循环嵌套的终止结合便签使用
- Outter@for(...){
Inner@while(i < 0){ if(...) break } //结束while循环
Inner@while(i < 0){ if(...) break@Outter }//结束外层for循环
}
具名参数
- 给函数的时参附上形参
- 举例:
- fun sum(arg1:Int,arg2:Int) = arg1 + arg2
- sum(arg1 = 2, arg2 = 3)
变长参数
- 某个参数可以接收多个值
- 可以不为最后一个参数
- 如果传参时有歧义,需要使用具名参数
fun main(vararg args: String) {
// for (arg in args) {
// println(arg)
// }
hello(18.0,1,2,3,4,string ="Hello")
val array = intArrayOf(5,4,3,2,1)
hello(18.0,*array,string ="Hello")
}
fun hello(double: Double,vararg ints: Int, string: String) {
ints.forEach(::println)
}
1
2
3
4
5
4
3
2
1
本章知识点示例
fun main(args: Array) {
while (true) {
try {
println("请输入算式例如:3 + 4")
val input = readLine() ?: break
if (input != null) {
val splits = input.trim().split(" ")
if (splits.size < 3) {
throw IllegalArgumentException("参数个数不对")
}
val arg1 = splits[0].toDouble()
val op = splits[1]
val arg2 = splits[2].toDouble()
println("$arg1 $op $arg2 = ${Operator(op).apply(arg1, arg2)}")
}
} catch (e: NumberFormatException) {
println("您输入的数字格式不对")
} catch (e: IllegalArgumentException) {
println("请输入用空格分隔的三个参数")
} catch (e:Exception){
println("未知异常:${e.message}")
}
println("再来一发?[Y]")
val cmd = readLine()
if (cmd == null || cmd.toLowerCase() != "y") {
break
}
}
}
class Operator(op: String) {
val opFun: (left: Double, right: Double) -> Double
init {
opFun = when (op) {
"+" -> { l, r -> l + r }
"-" -> { l, r -> l - r }
"*" -> { l, r -> l * r }
"/" -> { l, r -> l / r }
"%" -> { l, r -> l % r }
else -> {
throw UnsupportedOperationException(op)
}
}
}
fun apply(left: Double, right: Double): Double {
return opFun(left, right)
}
}
请输入算式例如:3 + 4
566.33.33 + 1
您输入的数字格式不对
再来一发?[Y]
y
请输入算式例如:3 + 4
23+1
请输入用空格分隔的三个参数
再来一发?[Y]
y
请输入算式例如:3 + 4
5 + 6
5.0 + 6.0 = 11.0
再来一发?[Y]