1. 程式人生 > >Java:函式式介面、方法引用

Java:函式式介面、方法引用

1、函式式介面-概念及格式

函式式介面:有且只有一個抽象方法的介面(可以有其他的方法:預設方法,靜態方法,私有方法…)

2、函式式介面[email protected]註解

1)、在定義函式式介面時,為防止發生定義錯誤,可使用@FunctionalInterface註解,強制按照函式式介面的語法進行檢查,如果語法錯誤,編譯器會編譯錯誤

@FunctionalInterface
interface IA{//如果此介面不定義任何抽象方法,將會報錯
	public void show();
	public void show1();//如果此介面定義多個抽象方法,也會報錯
}

3、函式式介面-練習-自定義函式式介面(無參無返回值)

//無參,無返回值的函式式介面
@FunctionalInterface
interface IA{
    public void show();
}

public class Demo {
    public static void main(String[] args) {        
        //2.使用Lambda表示式,代替"匿名內部類"
        fun(() -> System.out.println("呵呵...."));
    }
    public static void fun(IA a){
        a.show();
    }
}

4、函式式介面-練習-自定義函式式介面(有參有返回值)

@FunctionalInterface
interface IA{
    public int calc(int a, int b);
}
public class Demo {
    public static void main(String[] args) {
        //2.使用Lambda
        fun((int m, int n) -> {
            return m + n;
        }, 10, 20);
    }

    public static void fun(IA a,
int x, int y) { int result = a.calc(x, y); System.out.println("結果是:" + result); } }

5、函數語言程式設計-Lambda的應用-延遲執行

@FunctionalInterface
interface IA{
    public String buildString();
}
public class Demo {
    public static void main(String[] args) {
        String s1 = "日誌級別:1";
        String s2 = "異常資訊:NullPointerException";
        String s3 = "日期:2018-09-22";
        //1.使用匿名內部類的方式
        fun(1, new IA(){
            @Override
            public String buildString() {
                System.out.println("執行了....");
                return s1 + s2 + s3;
            }
        });

        //2.使用Lambda代替匿名內部類
        fun(1,()->{
            System.out.println("執行啦.....");
            return s1 + s2 + s3;});

    }

    //一個列印日誌
//    public static void fun(int level, String msg) {//原方法
    public static void fun(int level, IA a) {//改為介面型別形參
        if (level == 1) {//只有級別為1時,才打印日誌--延遲
            System.out.println(a.buildString());
        }
    }
}

6、函數語言程式設計-Lambda的應用-自定義介面-Lambda作為引數和返回值

@FunctionalInterface
interface IA{
    public void show();
}
public class Demo {
    public static void main(String[] args) {
        //Lambda作為形參
        f1(() -> System.out.println("呵呵呵"));
        //Lambda作為返回值
        IA a = f2();
        a.show();
        
    }

    //作為"形參"
    public static void f1(IA ia) {
        ia.show();
    }
    
    //作為"返回值"
    public static IA f2(){
        return () -> System.out.println("嘻嘻...");
    }
}

函式式介面作為形參時,必須要使用這個介面的實現子類來作為實參,而這個實現子類又必須要重寫介面的抽象方法,所以就可以直接使用Lambda表示式作為實參傳入(做返回值同樣)

7、函數語言程式設計-Lambda的應用-類庫介面-Lambda作為形參和返回值

public class Demo {
    public static void main(String[] args) {
        //1.Lambda作為形參
        f1(()-> System.out.println("執行緒啟動!"));
        //2.Lambda作為返回值
        Runnable r = f2();
        new Thread(r).start();
        

    }

    //使用Lambda作為"形參"
    public static void f1(Runnable runnable) {
        new Thread(runnable).start();
    }

    //使用Lambda作為"返回值"
    public static Runnable f2(){
        return () -> System.out.println("執行緒啟動....");
    }
}

8、方法引用-使用自定義靜態方法替代Lambda(“引用”理解為“替代”)

方法引用:就是使用已存在的方法替代Lambda表示式

@FunctionalInterface
interface IA{
    public void show();
}
public class Demo {
    public static void main(String[] args) {

       fun(Demo::method);//Demo::method代替:Lambda,Lambda代替:匿名內部類。

        fun(Demo::f2);//OK的--靜態方法,必須通過"類名"引用,不能通過"物件名"引用。

        fun(Demo::f3);//錯誤的,因為其引數不同

    }

    public static void fun(IA ia) {
        ia.show();
    }

    //其它方法
    public static void method(){
        System.out.println("呵呵...");
    }

    private static void f2(){
        System.out.println("嘻嘻....");
    }

    public static void f3(String s) {
        System.out.println(s);
    }
}

9、方法引用-使用類庫靜態方法替代Lambda

@FunctionalInterface
interface IA{
    //列印一個int陣列的所有元素
    public String printArray(int[] arr);
}
public class Demo {
    public static void main(String[] args) {
        int[] arr = {1432,432,432,4325,424,324,32,54,51,412,35,25,144,3};
        //使用匿名內部類
        fun(new IA(){
            @Override
            public String printArray(int[] arr) {
                StringBuilder bld = new StringBuilder("[");
                for (int i = 0; i < arr.length; i++) {
                    bld.append(arr[i]);
                    if (i < arr.length - 1) {
                        bld.append(" ,");
                    }else{
                        bld.append("]");
                    }
                }
               return bld.toString();
            }
        },arr);

        //使用Lambda
        fun((int[] array) -> {
            StringBuilder bld = new StringBuilder("[");
            for (int i = 0; i < array.length; i++) {
                bld.append(array[i]);
                if (i < array.length - 1) {
                    bld.append(" ,");
                } else {
                    bld.append("]");
                }
            }
            return bld.toString();
        }, arr);

        //使用Arrays的toString()方法來替代:Lambda
        fun(Arrays::toString, arr);
    }

    //定義方法,可以列印陣列
    public static void fun(IA a, int[] arr) {
        System.out.println(a.printArray(arr));
    }
}

10、方法引用-替代原則

“替代的方法”的形參、返回值型別,必須和被替換的“函式式介面”中的抽象方法一致

11、方法引用-使用物件成員方法替代Lambda

@FunctionalInterface
interface Game{
    public void run();
}
class Student{
    public void playGame(Game game) {
        System.out.println("我開始打遊戲:");
        game.run();
    }
}

class Teacher{
    public void like(){
        System.out.println("我喜歡喝茶(我是老師).....");
    }
}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.playGame(()-> System.out.println("王者榮耀開始執行....."));
        stu.playGame(()-> System.out.println("我喜歡喝茶...."));

        //使用Teacher類的like()方法來代替Lambda表示式,列印:我喜歡喝茶....
        Teacher t = new Teacher();
        stu.playGame(t::like);//引用Teacher的like()方法。
	  //或者
        stu.playGame(new Teacher()::like);
    }
}

12、方法引用-使用super父類方法替代Lambda

@FunctionalInterface
interface Game{
    public void run();
}
class Fu{
    public void like(){
        System.out.println("我喜歡喝啤酒(我是父親)....");
    }
}
class Student extends Fu{
    public void playGame(Game game) {
        System.out.println("我開始打遊戲:");
        game.run();
    }

    public void show(){
	   //1.使用Lambda
        playGame(() -> System.out.println("我喜歡喝啤酒...."));
	   //2.使用父類的like方法代替Lambda表示式
        playGame(super::like);//使用父類的like方法代替Lambda表示式
    }

}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.show();
    }
}

13、方法引用-使用this本類方法替代Lambda

@FunctionalInterface
interface Game{
    public void run();
}

class Student{
    public void playGame(Game game) {
        System.out.println("我開始打遊戲:");
        game.run();
    }

    public void show(){
//        playGame(() -> System.out.println("我喜歡打羽毛球...."));
        playGame(this::ymq);
    }

    public void ymq(){
        System.out.println("我喜歡打羽毛球....");
    }
}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.show();
    }
}

14、方法引用-類的構造器引用

1)、無參的構造方法

class Cat{
    public Cat(){
    }
    public void eat(){
        System.out.println("小貓吃魚....");
    }
}

interface CatFactory{
    //生產Cat
    public Cat getCat();
}

public class Demo {
    public static void main(String[] args) {
        //呼叫fun
        //1.使用:匿名內部類
        fun(new CatFactory() {
            @Override
            public Cat getCat() {
                return new Cat();
            }
        });

        //2.使用Lambda表示式
        fun(()->{return new Cat();});

        //3.使用Cat的無參構造方法替代:getCat()方法
        fun(Cat::new);
    }

    public static void fun(CatFactory cf) {
        Cat c = cf.getCat();
        c.eat();
    }
}

2)、有參構造方法

class Cat{
    private String name;
    public Cat(){
    }
    public Cat(String name) {
        this.name = name;
    }

    public void eat(){
        System.out.println("我是一隻 " + name + " 我愛吃魚....");
    }
}

interface CatFactory{
    //生產Cat
    public Cat getCat(String name);
}

public class Demo {
    public static void main(String[] args) {
        //呼叫fun
        //1.使用:匿名內部類
        fun(new CatFactory() {
            @Override
            public Cat getCat(String name) {
                return new Cat(name);
            }
        },"機器貓");

        //2.使用Lambda表示式
        fun((String n)->{return new Cat(n);},"機器貓");

        //3.使用Cat的有參構造方法替代:getCat(String name)方法
        fun(Cat::new,"機器貓");
    }

    public static void fun(CatFactory cf,String name) {
        Cat c = cf.getCat(name);
        c.eat();
    }
}

15、方法引用-陣列構造器引用

@FunctionalInterface
interface IA{
    public int[] getArr(int len);
}

public class Demo {
    public static void main(String[] args) {
        //2.使用Lambda
        fun(