美文网首页Android开发Android开发经验谈Kotlin
Kotlin-第3节、函数与Lambda闭包

Kotlin-第3节、函数与Lambda闭包

作者: JuliusL | 来源:发表于2018-10-22 13:44 被阅读13次

    目录:
    1、函数的特性语法
    2、嵌套函数
    3、扩展函数
    4、Lambda闭包语法
    5、高阶函数
    6、内联函数

    1、函数的特性语法

    • 函数的参数可以声明默认值
    • 如果函数体只有一个语句的话,可以将该语句直接赋值给该函数。
    fun echo(name:String){
        println("$name")
    }
    fun echo(name:String = "Zhangtao"){
        println("$name")
    }
    fun echo(name:String) = println("$name")
    

    2、函数嵌套

    用途:在某些情况下出发递归的函数,或不希望被外部函数访问到的函数。

    fun function(){
        val str = "hello world"
        fun say(count:Int = 10){
            println(str)
            if(count>0){
                say(count - 1)
            }
        }
        say()
    }
    

    3、扩展函数

    kotlin特性:静态给一个类扩展成员方法和成员变量。
    用类名点方法名的方式

    //给File类扩展一个readText方法
    fun File.readText(charset:Charset = Charsets.UTF-8):String=readBytes().toString(charset)
    
    //调用
    fun main(args:Array<String>){
        val file = File("Project2.iml")
        println(file.readText())
    }
    

    java如何使用kotlin的扩展函数呢?

    public class Main{
        public static void main(String[] args){
            File file = new File("project2.iml");
            String content = FilesKt.readText(file,Charsets.UTF-8);
            System.out.println(content);
        }
    }
    

    注:该扩展函数并不是File本身的函数,它编译的时候会被编译到那个类对应的class里面去,在java中我们调用的是FileKt,第一个参数是需要扩展这个类的对象,该参数不可省略。

    • 为什么说这是静态的扩展呢?
    //open值得是不final,与java的final相反的意思
    open class Animal
    class Dog:Animal()
    
    //分别给其添加扩展方法
    fun Animal.name() = "animal"
    fun Dog.name() = "dog"
    
    fun Animal.printName(anim:Animal){
        println(anim.name())
    }
    
    fun main(args:Array<String>){
        Dog().printName(Dog())//这里输出animal
    }
    
    • kotlin的扩展函数它实际上是静态的给一个类添加的,它是不具备运行时的一个多态效应的。

    编译完之后:

    public static final String name(Animal receiver){
        return "animal";
    }
    public static final String name(Dog receiver){
        return "dog";
    }
    public static final void printName(Animal r,Animal a){
        String str = name(a)
        System.out.println(str);
    }
    public static final void main(String [] args){
        //强转成了animal
        printName((Animal)new Dog(), (Animal)new Dog());
    }
    

    4、kotlin的lambda闭包

    public static void main(String[] args){
        Thread thread = new Thread(new Runnable(){
            public void run(){
                // ...
            }
        });
        thread.start();
    }
    

    Java8的Lambda语法:

    • 将Runnable对象省略成()-> 的形式替代。
    public static void main(String[] args){
        Thread thread = new Thread(() -> {
            //...
        });
        thread.start();
    }
    

    kotlin的Lambda语法:

    fun main(args:Array<String>){
        val thread = Thread({  -> Unit })
        thread.start()
    }
    
    • 如果Lambda没有参数,可以省略箭头符号->
    fun main(args:Array<String>){
        val thread = Thread({})
        thread.start()
    }
    
    • 如果Lambda是函数的最后一个参数,可以将大括号放在小括号外面
    fun main(args:Array<String>){
        val thread = Thread(){}
        thread.start()
    }
    
    • 最简单形态:如果函数只有一个参数且这个参数是Lambda,则可以省略小括号
    fun main(args:Array<String>){
        val thread = Thread{ }
        thread.start()
    }
    
    • 如果Lambda只有一个参数的话,可以不写,然后用it去替代它。
    val letResult = user.let(user:User->"let::${user.javaClass}")
    |
    |
    val letResult = user.let{"let::${it.javaClass}"}
    

    Lambda闭包声明

    //name:String:参数
    //->:闭包体
    val echo = { name:String ->
        println(name)
    }
    fun main(args: Array<String>){
        echo.invoke("hello")
        echo("hello ")
    }
    
    • Lambda参数有上限22个。
    • 如果传23个,会抛出NoClassDefFoundError,因为编译成class的时候,会编译成Funcation23,但是内置最多Funcation22,所以才会找不到。
    fun onlyif(isDebug:Boolean,block:()->Unit){
        if (isDebug)block()
    }
    fun main(args:Array<String>):Unit{
        onlyif(true){
            println("打印日志")
        }
    }
    
    • 注意:main函数中onlyif(true)用大括号括起来的部分是Lambda函数(onlyif第二参),当Lambda作为函数的最后一个参数时,可以写在函数的小括号之外。

    5、高阶函数

    重点:函数是“一等公民”

    • 对象.函数,这种是函数的调用。
    • 如果要把函数当做参数传递,需要传递一个函数的声明。
    • 如果传递的是“执行函数”的话,传递的实际上是函数的返回值。
    val runnable = Runnable{
        println("Runnable::run")
    }
    //声明一个参数为空,无返回值的函数对象
    val funcation:() -> Unit
    //将runnable的run方法赋值给声明好的函数
    function = runnable::run
    //将该函数作为参数传递给onlyif
    onlyif(true,function)
    

    6、用内联优化代码

    • Kotlin的Lambda是一个匿名对象
    • 可以使用inline修饰方法,这样当方法在编译时就会拆解方法的调用为语句调用,进而减少创建不必要的对象。

    创建方式:在高阶函数之前增加inline关键字。

    inline fun onlyif(isDebug:Boolean,block:()->Unit){
        if (isDebug)block()
    }
    fun main(args:Array<String>):Unit{
        onlyif(true){
            println("打印日志")
        }
    }
    

    编译后的class:

    public static final void onlyif(boolean isDebug,Function0<Unit>block){
        if(isDebug){
            block.invoke();
        }
    }
    public static final void main(String[] args){
        //拆解成了语句调用
        boolean isDebug = true;
        if(isDebug){
            String str = "打印日志";
            System.out.println(str);
        }
    }
    

    过分使用inline关键字会造成:

    • 增加编译器编译的负担。
    • 使得代码块变得庞大。

    相关文章

      网友评论

        本文标题:Kotlin-第3节、函数与Lambda闭包

        本文链接:https://www.haomeiwen.com/subject/nzkmzftx.html