一、 Kotlin语法

1. 变量与常量

<修饰符> <变量/常量名>[:类型] = [值]

在一般情况下:[类型]可省略,编译器进行类型推导

常量:
//val 修饰的为常量,不可再次赋值
val FINAL_HELLO_WORLD :String = "Hello World"

val USER_TYPE = "Admin"
变量:
//var 修饰的为变量,值可变化
var index:Int =1
//index 自增
index++

var username="ZhangSan"
字符串模板:

在Kotlin中可使用字符串模板来实现字符串中输出变量/常量值

var username="ZhangSan"
fun main(args:Array<String>){
    username = args[0]
    println("欢迎 ${username} 登录系统!")
}

2. 函数(得函数者得天下)

  • [函数修饰符] [函数名称]([参数列表])[:返回值类型]{[函数体]}

  • [函数修饰符] [函数名称]([参数列表])=[表达式]

  • 注:[]中的内容可省略,编译器可进行类型推导得出


 // 根据时间字符串返回日期
private fun getDate(dateStr:String): Date {
    val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    return sdf.parse(dateStr)
}


// 传入两个整形数,计算他们的和并输出
fun add(num1:Int,num2:Int){
    println("$num1 + $num2 = ${num1+num2}")
}

// 传入姓名,输出 Hi [传入的姓名]
fun sayHi(name:String)=println("Hi $name")

  • 匿名函数

匿名函数就是没有函数名称的函数,但是匿名函数必须赋值给一个变量/常量

// 匿名函数
val sayHi = fun(name:String)=println("Hi $name")

3. Lambda 表达式

Lambda 表达式 就是匿名函数

  • 语法:{[参数列表] -> [函数体,最后一行是返回值]}
例如:
val sum = {a:Int,b:Int -> a+b}
  • Lambda 表达式类型表示
// 无参,返回值为Unit
() -> Unit

// 传入整型,返回一个整型
(Int) -> Int

// 传入字符串、Lambda表达式,返回Boolean
(String,(String) -> String) -> Boolean
  • Lambda 表达式的调用

用()进行调用

等价于 invoke()

val sum = {a:Int,b:Int -> a+b}
sum(2,3)
sum.invoke(2,3)
  • Lambda 表达式的简化

函数参数调用时最后一个Lambda可以移出去

函数参数只有一个Lambda,调用时小括号可以省略

Lambda只有一个参数可以默认为it

入参、返回值与形参一致的函数可以用函数的引用的方式作为实参传入

val arr: Array<String> = arrayOf("1","s","sd","rer","54","65")

// Lambda 表达式 ,传入it ,并且打印it
// Lambda只有一个参数可以默认为it
arr.forEach({it -> println(it)})

// 上面的Lambda 表达式简化后
// Lambda只有一个参数可以默认为it
// 函数参数调用时最后一个Lambda可以移出去
arr.forEach(){println(it)}

// 上面的Lambda 表达式简化后
// Lambda只有一个参数可以默认为it
// 函数参数只有一个Lambda,调用时小括号可以省略
arr.forEach{println(it)}

// 上面的Lambda 表达式简化后
// Lambda只有一个参数可以默认为it
// 入参、返回值与形参一致的函数可以用函数的引用的方式作为实参传入
arr.forEach(::println)



// 判断数组中值为rer 是跳出本次循环,继续下次循环,相当于continue

 arr.forEach ForEach@{
     if(it == "rer") return@ForEach
     println(it)
 }

// 判断数组中值为rer 是跳出循环,不再进行下面的循环,继续制作该循环后面的代码
 run breaking@ {
     arr.forEach {
        if(it == "rer") return@breaking
        println(it)
    }}

3. 类成员

  • 属性:或者说成员变量,类范围内的变量
  • 方法:或者说成员函数,类范围内的函数

函数和方法的区别:

函数强调功能本身,不考虑从属

方法的称呼通常是从类的角度出发

只是叫法不同而已

  • 定义属性

构造方法参数中val/var 修饰的都是属性

类内部也可以定义属性

class Hello(val aFiled:Int,notAField:Int){
    var anotherField:Float = 3f
}
  • 属性访问控制

属性可以定义getter/setter

val a: Int=0
    get()=field

var b: Float = 0f
    get(){
        return field / 3;
    }
    set(value){field = value}
  • 属性初始化

属性的初始化尽量在构造方法中完成

无法在构造方法中初始化,尝试降级为局部变量

var 用 lateinit 延迟初始化,val 用 lazy 延迟初始化

可空类型谨慎用 null 直接初始化

4. 运算符( ±*/%^? )

官网定义

Expression Translated to
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a++ a.inc() + see below
a– a.dec() + see below
a+b a.plus(b)
a-b a.minus(b)
a*b a.times(b)
a/b a.div(b)
a%b a.rem(b),a.mod(b)(deprecated)
a…b a.rangeTo(b)
a in b b.contains(a)
a !in b !b.contains(a)
a[i] a.get(i)
a[i,j] a.get(i,j)
a[i_1,…,i_n] a.get(i_1,…,i_n)
a[i] = b a.set(i,b)
a[i,j] = b a.set(i,j,b)
a[i_1,…,i_n] =b a.set(i_1,…,i_n,b)
a() a.invoke()
a(i) a.invoke(i)
a(i,j) a.invoke(i,j)
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.modAssign(b)
  • 基本运算符

任何类可以定义或者重载父类的基本运算符

通过运算符对应的具名函数来定义

对参数的个数做要求,对参数和返回值类型不做要求

不能像 Scala 一样定义人与运算符

// 定义一个复数,实部与实部相加,虚部与虚部相加
class Complex(var real: Double,var imaginary: Double){
    operator fun plus(other: Complex):Complex{
        return Complex(real+other.real,imaginary + other.imaginary)
    }
    override fun toString():String{
        return "$real + ${imaginary}i"
    }
}


fun main(args: Array<String>){
    val c1 = Complex(3.0,4.0)//3.0+4.0i
    val c2 = Cpmplex(2.0,7.5)//2.0+7.5i
    println(c1 + c2)
}
  • 中缀表达式

只有一个参数,且用infix 修饰的函数

class Book {
    infix fun on(place:String){...}
}

Book() on "My Desk"
  • 分支表达式

  • if 表达式
    if … else

if(a == b) ... else if(a == c) ... else ...

表达式与完备性

val x = if(b<0) 0 else b

val x = if(b<0)0 //错误,赋值时,分支必须完备
  • when 表达式

加强版的 switch ,支持任意类型

支持纯表达式条件分支(类似if)

表达式与完备性特性

  • 循环语句

基本写法:
for(element in elements) …

给任意类实现 Iterator 方法

val arr: Array<String> = arrayOf("1","s","sd","rer","54","65")

for(a in arr){
    println(a)
}


for((index,value) in arr.withIndex()){
    println("$index -> $value")
}

for(indexedValue in arr.withIndex()){
    println("${indexedValue.index} -> ${indexedValue.value}")
}


class MyIterator(val iterator: Iterator<Int>){
    operator fun next():Int{
        return iterator.next
    }

     operator fun hasNext():Boolean{
        return iterator.hasNext()
    }
}

cal MyIntList{
    private val list = ArrayList<Int>()

    fun add(int: Int){
        list.add(int)
    }

    fun remove(int: Int){
        list.remove(int)
    }

    operator fun iterator():MyIterator{
        return MyIterator(list.iterator())
    }
}


fun main(args: Array<String>){
    val list = MyIntList()
    list.add(1)
    list.add(2)
    list.add(3)

    for(i in list){
        println(i)
    }

}

// while
var x=5
while(x>0){
    println(x)
    x--
}


do{
   println(x)
    x--
}while(x>0)
  • 跳出或跳过循环

跳出,终止循环 break

跳过当前循环 continue

多层循环嵌套的终止结合标签使用

Outter@for(...){
    Inner@while(i<0){
        if(...) break@Outter
    }
}

5. 异常捕获

使用 try{}catch(e: Exception){} 进行异常捕获

try{  
    //程序正常执行
}catch(e: Exception){
    //程序出现异常,可根据异常类型捕获相应的异常
}finally{
    //无论执行成功还是出现异常都会执行
}

6. 具名参数

给函数的实参附上形参

fun sum(arg1:Int,arg2:Int) = arg1 + arg2

sun(arg2=3,arg1=2)

7. 变长参数

使用 vararg 修饰

某个参数可以接受多个值

可以不为最后一个参数

如果传参是由歧义,需要使用具名参数

8. Spread Operator

使用 * 来展开

只支持展开Array

只用于变长列表的实参

val arr=intArrayOf(1,2,3,4,5)

fun printMethod(vararg arrs:Int){
    arrs.forEach(::println)
}

printMethod(*arr)

9.默认参数

为函数参数指定默认值

可以为任意位置的参数指定默认值

传参时,如果有歧义,需要使用具名参数

val arr=intArrayOf(1,2,3,4,5)

fun printMethod(name:String = "admin",vararg arrs:Int){
    arrs.forEach(::println)
}

printMethod(arrs=*arr)

10. 导出可执行程序

  • 在build.gradle 中增加
apply plugin: 'application'
mainClassName = ""//程序入口类路径,Kotlin文件名后加 Kt
  • gradle 刷新/同步
  • gradle 中的distribution 中点击installDist得到可执行的文件
  • 在项目目录下的build文件夹下的install文件夹下
//命令行输入:
# cd build/install/[项目名称]
# chmod 755 bin/[项目名称]
# bin/[项目名称]