首頁  >  文章  >  Java  >  Java中Lambda表達式使用的方法是什麼

Java中Lambda表達式使用的方法是什麼

WBOY
WBOY轉載
2023-06-03 16:55:541185瀏覽

    一、Lambda表達式的簡介

    Lambda表達式(閉包):java8的新特性,lambda運行將函數作為一個方法的參數,也就是函數作為參數傳遞到方法中。使用lambda表達式可以讓程式碼更簡潔。

    Lambda表達式的使用場景:用以簡化介面實作。

    關於介面實現,可以有很多種方式來實現。例如:設計介面的實作類別、使用匿名內部類別。但是lambda表達式,比這兩種方式都簡單。

    package test;
    /**
     * @author: Mercury
     * Date: 2022/3/20
     * Time: 17:48
     * Description:Lambda表达式
     * Version:1.0
     */
    public class Test04 {
        public static void main(String[] args) {
            //使用lambda表达式实现接口
            Test test = () -> {
                System.out.println("test");
            };
            test.test();
        }
    }
    interface Test{
        public void test();
    }

    二、Lambda表達式對介面的要求

    雖然說,lambda表達式可以在⼀定程度上簡化介面的實作。但是,並不是所有的介面都可以使用lambda表達式來簡潔實現的。

    lambda表達式畢竟只是⼀個匿名方法。當實作的介面中的方法過多或多少的時候,lambda表達式都是不適用的。

    lambda表達式,只能實作函數式介面。

    1.函數式介面

    如果說,⼀個介面中,要求實作類別必須實作的抽象方法,有且只有⼀個!這樣的接口,就是函數式接口。

    程式碼如下(範例):

    //有且只有一个实现类必须要实现的抽象方法,所以是函数式接口
    interface Test{
        public void test();
    }

    2.@FunctionalInterface

    是⼀個註解,用在介面之前,判斷這個介面是否是⼀個函數式介面。如果是函數式接口,沒有任何問題。如果不是函數式接口,則會報錯。功能類似於 @Override。
    程式碼如下(範例):

    @FunctionalInterface
    interface Test{
        public void test();
    }

    3.Lambda表達式的語法

    1.Lambda表達式的基礎語法

    lambda表達式,其實本質來講,就是⼀個匿名函數。因此在寫lambda表達式的時候,不需要關心方法名稱是什麼。

    實際上,我們在寫lambda表達式的時候,也不需要關心回傳值型別。

    我們在寫lambda表達式的時候,只需要關注兩部分內容即可:參數列表和方法體

    lambda表達式的基礎語法:
    (參數1,參數2,…) -> {
    方法體
    };

    參數部分:方法的參數列表,要求和實現的介面中的方法參數部分⼀致,包括參數的數量和類型。

    方法體部分 : 方法的實作部分,如果介面中定義的方法有回傳值,則在實作的時候,注意回傳值的回傳。

    -> : 分隔參數部分和方法體部分。

    程式碼範例:

    package test;
    /**
     * @author: Mercury
     * Date: 2022/3/20
     * Time: 17:48
     * Description:Lambda表达式
     * Version:1.0
     */
    public class Test04 {
        public static void main(String[] args) {
            //使用lambda表达式实现接口
            //无参
    //        Test test = () -> {
    //            System.out.println("test");
    //        };
            //有参
    //        Test test = (name,age) -> {
    //            System.out.println(name+age+"岁了!");
    //        };
    //        test.test("小新",18);
            //有参+返回值
            Test test = (name,age)  -> {
                System.out.println(name+age+"岁了!");
                return age + 1;
            };
            int age = test.test("小新",18);
            System.out.println(age);
        }
    }
    //无参
    //interface Test{
    //    public void test();
    //}
    //有参 无返回值
    //interface Test{
    //    public void test(String name,int age);
    //}
    //有参 有返回值
    interface Test{
        public int test(String name,int age);
    }

    4.Lambda表達式的語法進階

    參數部分的精簡

    參數的類型

    由於在介面的方法中,已經定義了每⼀個參數的型別是什麼。而且在使用lambda表達式實現介面的時候,必須確保參數的數量和類別 型需要和介面中的方法保持⼀致。因此,此時lambda表達式中的參數的型別可以省略不寫。

    注意點:

    如果需要省略參數的類型,要保證:要省略, 每⼀個參數的類型都必須省略不寫。絕對不能出現,有的參數型別省略了,有的參數型別沒有省略。

            //有参+返回值
            Test test = (name,age)  -> {
                System.out.println(name+age+"岁了!");
                return age + 1;
            };
            int age = test.test("小新",18);
            System.out.println(age);

    參數的小括號

    如果方法的參數清單中的參數數量有且只有⼀個,此時,參數清單的小括號是可以省略不寫的。

    注意事項:

    • 只有當參數的數量是⼀個的時候, 多了、少了都不能省略。

    • 省略掉小括號的同時,必須要省略參數的型別

    #
            //一个参数
            Test test = name -> {
                System.out.println(name+"test");
            };
            test.test("小新");

    方法體部分的精簡

    方法體⼤括號的精簡

    當⼀個方法體中的邏輯,有且只有⼀句的情況下,⼤括號可以省略

    Test test = name -> System.out.println(name+"test");
            test.test("小新");

    return的精簡

    如果⼀個方法中唯⼀的⼀條語句是⼀個回傳語句, 此時在省略掉大括號的同時, 也必須省略掉return。

    Test test = (a,b) -> a+b;

    三、函數引用

    lambda表達式是為了簡化介面的實作的。在lambda表達式中,不應該出現比較複雜的邏輯。過於複雜的邏輯在lambda表達式中的使用會大大影響程式的可讀性。通常情況下,如果lambda表達式需要處理複雜邏輯,我們會單獨寫一個方法來處理。在lambda表達式中直接引用這個方法即可。

    函數引用:引用⼀個已經存在的方法,使其取代lambda表達式完成介面的實作

    1.靜態方法的引用

    語法:類別::靜態方法

    注意事項:

    • #在引用的方法後面,不要新增小括號。

    • 引用的這個方法,參數(數量、型別)和回傳值,必須跟介面中定義的⼀致

    package test;
    /**
     * @author: Mercury
     * Date: 2022/3/20
     * Time: 18:17
     * Description:lambda表达式静态方法引用
     * Version:1.0
     */
    public class Test05 {
        public static void main(String[] args) {
            //实现多个参数,一个返回值的接口
            //对一个静态方法的引用,语法:类::静态方法
            Test1 test1 = Calculator::calculate;
            System.out.println(test1.test(4,5));
        }
    }
    class Calculator{
        public static int calculate(int a,int b ){
            // 稍微复杂的逻辑:计算a和b的差值的绝对值
            if (a > b) {
                return a - b;
            }
            return b - a;
        }
    }
    interface Test1{
        int test(int a,int b);
    }
    package test;
    /**
     * @author: Mercury
     * Date: 2022/3/20
     * Time: 18:17
     * Description:lambda表达式静态方法引用
     * Version:1.0
     */
    public class Test05 {
        public static void main(String[] args) {
            //实现多个参数,一个返回值的接口
            //对一个静态方法的引用,语法:类::静态方法
            Test1 test1 = Calculator::calculate;
            System.out.println(test1.test(4,5));
        }
    }
    class Calculator{
        public static int calculate(int a,int b ){
            // 稍微复杂的逻辑:计算a和b的差值的绝对值
            if (a > b) {
                return a - b;
            }
            return b - a;
        }
    }
    interface Test1{
        int test(int a,int b);
    }

    2 .非靜態方法的參考

    語法:物件::非靜態方法

    #注意事項:

    • 在引用的方法後面⾯,不要加上小括號。

    • 引用的这个方法, 参数(数量、类型) 和 返回值, 必须要跟接口中定义的⼀致。

    package test;
    /**
     * @author: Mercury
     * Date: 2022/3/21
     * Time: 8:14
     * Description:lambda表达式对非静态方法的引用
     * Version:1.0
     */
    public class Test06 {
        public static void main(String[] args) {
            //对非静态方法的引用,需要使用对象来完成
            Test2 test2 = new Calculator()::calculate;
            System.out.println(test2.calculate(2, 3));
        }
        private static class Calculator{
            public int calculate(int a, int b) {
                return a > b ? a - b : b - a;
             }
        }
    }
    interface Test2{
        int calculate(int a,int b);
    }

    3.构造方法的引用

    使用场景

    如果某个函数式接口中所定义的方法只是为了获取一个类的对象。此时我们就可以使用构造方法的引用,简化这个方法的实现。

    语法:类名::new

    注意事项:可以通过接口中的方法的参数, 区分引用不同的构造方法。

    package com.cq.test;
    /**
     * @author: Mercury
     * Date: 2022/4/27
     * Time: 10:31
     * Description:lambda构造方法的引用
     * Version:1.0
     */
    public class Test {
        private static class Dog{
            String name;
            int age;
            //无参构造
            public Dog(){
                System.out.println("一个Dog对象通过无参构造被实例化了");
            }
            //有参构造
            public Dog(String name,int age){
                System.out.println("一个Dog对象通过有参构造被实例化了");
                this.name = name;
                this.age = age;
            }
        }
        //定义一个函数式接口,用以获取无参的对象
        @FunctionalInterface
        private interface GetDog{
            //若此方法仅仅是为了获得一个Dog对象,而且通过无参构造去获取一个Dog对象作为返回值
            Dog test();
        }
        //定义一个函数式接口,用以获取有参的对象
        @FunctionalInterface
        private interface GetDogWithParameter{
            //若此方法仅仅是为了获得一个Dog对象,而且通过有参构造去获取一个Dog对象作为返回值
            Dog test(String name,int age);
        }
        // 测试
        public static void main(String[] args) {
            //lambda表达式实现接口
            GetDog lm = Dog::new; //引用到Dog类中的无参构造方法,获取到一个Dog对象
            Dog dog = lm.test();
            System.out.println("修狗的名字:"+dog.name+" 修狗的年龄:"+dog.age); //修狗的名字:null 修狗的年龄:0
            GetDogWithParameter lm2 = Dog::new;//引用到Dog类中的有参构造,来获取一个Dog对象
            Dog dog1 = lm2.test("萨摩耶",2);
            System.out.println("修狗的名字:"+dog1.name+" 修狗的年龄:"+dog1.age);//修狗的名字:萨摩耶 修狗的年龄:2
        }
    }

    四、Lambda表达式需要注意的问题

    这⾥类似于局部内部类、匿名内部类,依然存在闭包的问题。

    如果在lambda表达式中引用了局部变量,则该局部变量会隐式声明为final变量。是⼀个常量,不能修改值。

    以上是Java中Lambda表達式使用的方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除