Kotlin变量和函数

程序结构

变量和常量

常量

在Kotlin中,val相当于常量,类似于Java中的final,例如:

val HELLO_WORLD = "HELLO WORLD"//可以自己进行推导类型

val在Kotlin中是编译期常量,常量只有get方法,没有对应的set方法,值必须初始化,且不可被修改,但是实际工作中并不一定见得就会初始化为想要的值,所以应用的时候,应该加一个lateinit,延迟初始化

变量

变量使用var来表示,var标注的值是可以修改的。对应的set get方法都会有,但是如果没有初始值,且不能为null的话,还是需要使用来进行初始化

lateinit var name : String

####函数

函数定义

函数使用fun进行声明,如果函数不是成员函数的话,可以直接进行调用,若为成员函数,则需要使用实例进行调用,Kotlin中,函数的参数必须有显式类型,采用Pascal表示法定义,例如:

fun powerOf(number:Int,exponent:Int){
    //...
}

默认值

函数可以拥有默认值,而且覆盖一个带有默认值的方法的时候,必须从签名中省略默认参数值,例如:

open class A{
    open fun foo(i:Int = 10){...}
}
open class B : A(){
    override fun foo(i:Int){...}//不能有默认值
}

命名参数调用函数

Kotlin中可以使用命名参数的方式调用函数,而且如果函数中有默认参数,且一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用命名参数调用该函数来使用,但是如果最后一个是_lambda_表达式的话,则允许默认参数不传值

fun foo(bar:Int = 0 , baz : Int,bun : Int){...}
foo(baz = 1,bun = 2) //默认值bar = 0 

可变参数

不同于Java中的String ... str,在Kotlin中,使用_vararg_来表示:

fun foo(vararg strings : String){...}
foo(strings=*arrayOf("a","b","c"))//多个值的话,可以使用*操作符将vararg变量以命名形式传入
foo(strings = "a")//单个值的话则不需要*操作符

void

Kotlin中没有void返回值,每个函数都由返回类型,但是如果需要一个类似于Java中void的函数的时候,可以使用Unit返回值类型,这种类型不需要进行显示声明
单表达式函数

Kotlin中更多的是使用表达式,以使代码简约的同时保持可读性:

fun double(x:Int) = x * 2//单表达式可以省略函数,如果返回值类型可以由编译器进行推断的话,返回值类型也可以省略

中缀表示法

只能是成员函数或者扩展函数;只能有一个参数,使用_infix_进行标注。例如:

infix fun Int.shl(x:Int):Int{
    //do something
}
1 shl 2 
//等同于
1.shl(2)

局部函数

后续补充…
泛型函数

后续补充…
内联函数

高阶函数会带来一些效率上的损失,这时使用内联函数的话,就可以消除这类的开销,类似于C语言的函数指针,例如:

inline fun<T> lock(lock:Lock,body: () -> T):T{
    //...
}
//lock()函数会被转换成下面的形式
l.lock()
try{
    foo()
}
finally{
    l.unlock()
}

若只想一部分内联,一部分不内联的话,则使用noinline来标记.例如:

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
    // ……
}

后续补充…
扩展函数

后续补充…
高阶函数和 Lambda 表达式

其实就是_函数式编程_,如下:

fun <T> lock(lock : Lock,body:() -> T):T{
    lock.lock()
    try{
        return body()
    }finally{
        lock.unlock()
    }
}

//传一个函数进行调用
fun toBeSynchronized() = shareResource.operation()
val result = lock(lock,::toBeSynchronized)
//使用lambda表达式
val result = lock(lock,{ sharedResource.operation() })

lambda简短描述:

  • ambda 表达式总是被大括号括着;
  • 其参数(如果有的话)在 -> 之前声明(参数类型可以省略);
  • 函数体(如果存在的话)在 -> 后面

    Lambda表达式或匿名函数可以访问其闭包,即在外部作用域中声明的变量。与 Java 不同的是可以修改闭包中捕获的变量:
var sum = 0
ints.filter{ it > 0 }.forEach{
    sum += it
}
println(sum)

后续补充…
尾递归函数

使用_tailrec_修饰符来标记,编译器会优化该递归,留下一个快速而高效的基于循环的版本:

tailrec fun findFixPoint(x: Double = 1.0):Double= if(x == Math.cos(x)) x else findFixPoint(Math.cos(x))

编译器优化过后的代码:

private fun findFixPoint():Double{
    var x = 1.0
    while(true){
        val y = Math.cos(x)
        if(x == y) return y
        x = y
    }
}

要符合 tailrec 修饰符的条件的话,函数必须将其自身调用作为它执行的最后一个操作。在递归调用后有更多代码时,不能使用尾递归,并且不能用在try/catch/finally 块中。目前尾部递归只在 JVM 后端中支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值