【函数式接口、方法引用】

标签: java  函数式接口  Lambda  方法引用

01.第一章:函数式接口_概念及格式:

1).概念:有且只有一个抽象方法的接口。(可以同时有默认方法、静态方法...)
2).格式:
    修饰符(public,默认) interface 接口名{
        public abstract void show();
        //可以同时有其它:默认方法、静态方法.....但不能再有抽象方法了
    }

02.第一章:函数式接口[email protected]注解:

1).为了让其它同事,项目组其它成员可以使用我们的类时,使用Lambda表达式,通常我们会主动的去设计并定义一些“函数式接口”,并且定义一些方法来使用这些接口作为参数,这样,当同事调用我们的方法时,就可以很方便的使用Lambda表达式。
2).定义“函数式接口”很简单--有且只有一个抽象方法即可。
3).JDK8同时为我们提供了一种“注解”[email protected]。它就类似于:
   @Override注解--强制重写父类方法。
   @FunctionalInterface注解强制修饰的接口为:函数式接口,否则编译错误;
4).示例代码:
@FunctionalInterface//告诉编译器:下面的接口是函数式接口
interface IA{
public void show();
default void show1(){
}
}

03.第一章:函数式接口练习自定义函数式接口(无参无返回值):

interface IA{
public void show();
}
class Zi implements IA{
public void show(){
    System.out.println("子类--show()....");
}
}
public class Demo {
public static void main(String[] args) {
    //1.方式一:子类对象
    fun(new Zi());
    //2.方式二:匿名内部类
    fun(new IA(){
        public void show(){
            System.out.println("匿名内部子类--show()....");
        }
    });
    //3.方式三:Lambda表达式--
    fun(()->{//使用"无名的方法"代替了子类的show()
        System.out.println("Lambda表达式--show()");
    });
}

private static void fun(IA a) {
    a.show2();//new Zi().show()//匿名子类.show()
}
}

04.第一章:函数式接口练习自定义函数式接口(有参有返回值):

interface IA{
public int calc(int a, int b);
}
class Zi implements IA{
@Override
public int calc(int a, int b) {
    return a + b;
}
}
public class Demo {
public static void main(String[] args) {
    //1.传递子类对象
    print(new Zi());//执行Zi中的加法
    //2.传递匿名内部子类对象
    print(new IA(){
        @Override
        public int calc(int a, int b) {
            return a * b;
        }
    });//执行匿名子类中的"乘法"
    //3.传递Labmda
    print((int x,int y)->{return x - y;});//执行Lambda中的"减法"
}

public static void print(IA ia) {
    int result = ia.calc(10, 20);
    System.out.println(result);
}
}

05.第二章:函数式编程Lambda的应用延迟执行:

1).未延迟:效率低:
public static void main(String[] args) {
String msg1 = "日期:2018-08-27";
String msg2 = "异常:NullPointerException";
String msg3 = "位置:Demo.java 13行";

printLog(2, msg1 + msg2 + msg3);
}

public static void printLog(int level, String msg) {
if (level == 1) {
    System.out.println("写入日志:");
    System.out.println(msg);
}else{
    System.out.println("不写日志:");
    System.out.println(msg);
}
}
2).延迟:效率高:
interface MessageBuilder{
public String buildMsg();
}

public class Demo {
public static void main(String[] args) {
    String msg1 = "日期:2018-08-27";
    String msg2 = "异常:NullPointerException";
    String msg3 = "位置:Demo.java 13行";
    //使用匿名内部子类对象
    printLog(2, new MessageBuilder() {
        @Override
        public String buildMsg() {
            System.out.println("开始拼接信息....");
            return msg1 + msg2 + msg3;
        }
    });
    //使用Lambda代替
    printLog(1,()-> msg1 + msg2 + msg3);
}

public static void printLog(int level, MessageBuilder mb) {
    if (level == 1) {
        System.out.println("写入日志:");
        System.out.println(mb.buildMsg());//调用方法,拼接字符串
    }else{
        System.out.println("不写日志:");
    //不调方法,不拼接字符串
    }
}
}

06.第二章:函数式编程Lambda的应用方法形参是自定义接口使用Lambda作为形参和返回值:

1).Lambda作为“形参”:当我们调用方法,发现方法定义了一个“接口”类型的形参,而且接口是一个“函数式接口--有且仅有一个抽象方法”,这时就可以传递一个Lambda:
    interface IA{
        public void show();
    }
    public class Demo{
        public static void main(String[] args){ 
            fun(()->{for(int i = 0;i < 10 ; i++){
                    System.out.println("Hello");
                    }});
        }
        public static void fun(IA a){
            a.show();
        }
    }
2).Lambda作为“返回值”:当我们“编写方法”时,可以定义返回值类型是一个“函数式接口类型”,如果是这样,可以返回一个Lambda表达式:
    interface IA{
        public void show();
    }
    public class Demo{
        public static void main(String[] args){ 
            IA a = getIa();
            a.show();
        }
        public static IA getIa(){
            return ()->System.out.println("呵呵...");
        }

    }

07.第二章:函数式编程练习方法形参是类库接口使用Lambda作为参数和返回值:

public class Demo{
    public static void main(String[] args){
        Runnable run = get();
        new Thread(run).start();
        //Lambda作为形参
        set(()->System.out.println("作为参数的Lambda线程启动..."));
    }
    //使用Lambda做返回值
    public static Runnabel get(){
        return ()->System.out.println("Lambda线程启动...");
    }
    public static void set(Runnable run){
        new Thread(run).start();
    }
}

08.第三章:方法引用_使用自定义静态方法替代Lambda:

interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
//      fun1(() -> System.out.println("呵呵"));
    fun1(Demo::method);//使用Demo类的method()方法代替:子类的show()、代替Lambda表达式
}

private static void fun1(IA a) {
    a.show();
}

public static void method() {
    System.out.println("呵呵");
}
}

09.第三章:方法引用_使用类库静态方法替代Lambda:

@FunctionalInterface
interface IA{
public int calc(int a, int b);
}
public class Demo {
public static void main(String[] args) {
    //1.使用Lambda做加法
    fun((x,y)-> x + y,10,20);

    //2.使用Lambda求最大值
 //   fun((x, y) -> x > y ? x : y);
    //3.使用Math类的max(int a,int b) 方法代替
    fun(Math::max,10,20);

}

public static void fun(IA ia,int t ,int k)    {
    int n = ia.calc(t, k);
    System.out.println("n = " + n);
}
}

10.第三章:方法引用_替代原则:

1).现有方法的“形参”和“返回值”要跟被替代的“抽象方法”的形参和返回值要一致。

11.第三章:方法引用_使用对象成员方法引用替代Lambda:

@FunctionalInterface
interface IGame{
public void run();
}
class Student{
public void playGame(IGame game) {
    game.run();
}
}
class Teacher{
public void reading(){
    System.out.println("老师喜欢读书....");
}
}
public class Demo {
public static void main(String[] args) {
    Student stu = new Student();
//        stu.playGame(()-> System.out.println("Lambda玩儿:王者荣耀"));
    Teacher t = new Teacher();
    stu.playGame(t::reading);
    stu.playGame(new Teacher()::reading);
}
}

12.第三章:方法引用_使用super父类方法替代Lambda:

@FunctionalInterface
interface IGame{
public void run();
}
class Fu{
public void like(){
    System.out.println("父亲喜欢喝酒...");
}
}
class Student extends Fu{
public void playGame(IGame game) {
    game.run();
}
public void like(){
    //super引用父类
   /*playGame(new IGame() {
       @Override
       public void run() {
           System.out.println("我喜欢喝啤酒....");
       }
   });
   playGame(()-> System.out.println("我喜欢喝啤酒...."));
playGame(()-> super.like());*/
   playGame(super::like);//这是"代替(引用),不是"调用"
}
}
public class Demo {
public static void main(String[] args) {
    Student stu = new Student();
    //super引用测试
    stu.like();
}
}

13.第三章:方法引用_使用this本类方法替代Lambda:

@FunctionalInterface
interface IGame{
public void run();
 }
class Student{
public void playGame(IGame game) {
    game.run();
}

 public void like(){
//预期打印:我喜欢羽毛球....
playGame(()-> System.out.println("我喜欢羽毛球..."));
playGame(()->this.show());
playGame(this::show);
}


public void running(){
    System.out.println("我喜欢跑步...");
}
public void show(){
    System.out.println("我喜欢羽毛球...");
}
}
public class Demo {
public static void main(String[] args) {
    Student stu = new Student();
    stu.like();
}
}

14.第三章:方法引用_类的构造器引用:

class Cat{
public void show(){
    System.out.println("小猫喵喵....");
}
}

interface CatFactory{
public Cat getCat();
}
public class Demo {
public static void main(String[] args) {
    myGetCat(new CatFactory() {
        @Override
        public Cat getCat() {
            return new Cat();
        }
    });

    myGetCat(()->new Cat());

    //使用构造引用
    myGetCat(Cat::new);
}

private static void myGetCat(CatFactory cf) {
    Cat c = cf.getCat();
    c.show();
}
}

15.第三章:方法引用_数组构造器引用:

interface IA{
public int[] makeArray(int length);
}
public class Demo {
public static void main(String[] args) {
    //1.Lambda
    fun((int len)->{ return new int[len]; },5);

    //2.数组构造引用
    fun(int[]::new, 10);
}

private static void fun(IA a, int len) {
    int[] arr = a.makeArray(len);
    System.out.println("新数组的长度:" + arr.length);
}
}

16.第四章:常用函数式接口_生产接口_Supplier接口:

public class Demo {
public static void main(String[] args) {
    setSpl(()->{return "Hello";});
    setSplInteger(()-> {return 10;});

}


public static void setSpl(Supplier<String> spl) {
        System.out.println(spl.get());
}

public static void setSplInteger(Supplier<Integer> intSpl) {
    System.out.println("一个int值:" + intSpl.get());
}
}

17.第四章:常用函数式接口消费接口_Consumer接口抽象方法accept:

public class Demo {
public static void main(String[] args) {
    f1((s)-> System.out.println(s),"Hello");

    f2((n)-> System.out.println(n),10);
}
public static void  f1(Consumer<String> c,String str){
    c.accept(str);

}

public static void f2(Consumer<Integer> c, Integer integer) {
    c.accept(integer);
}
}

18.第四章:常用函数式接口Consumer接口默认方法andThen:

这里写图片描述

public class Demo {
private static void consumeString(Consumer<String> one, 
                            Consumer<String> two) {
//        one. andThen(two). accept("Hello") ;
    new Consumer<String>(){
        @Override
        public void accept(String s) {
            one.accept(s);
            two.accept(s);
        }
    }.accept("Hello");
}
public static void main(String[ ] args) {
    consumeString(
            s -> System. out. println(s. toUpperCase()),
            s -> System. out. println(s. toLowerCase())
            );
}
}

学习目标总结:
01.能够使用@FunctionalInterface注解
1).必须在”函数式接口”上使用,强制编译器按照函数式接口的语法检查此接口。
2).示例:
@FunctionalInterface
interface IA{
public void show();
}
02.能够自定义无参无返回函数式接口
@FunctionalInterface
interface IA{
public void show();
}

03.能够自定义有参有返回函数式接口
@FunctionalInterface
interface IA{
public int calc(int a,int b);
}
public class Demo{
public static void main(String[] args){
f1((x,y)->x + y,10,20);
}
public static void f1(IA a,int x,int y){
System.out.println(a.calc(x,y));
}
}

04.能够理解Lambda延迟执行的特点
interface MessageBuilder{
public String buildMsg();
}

public class Demo {
public static void main(String[] args) {
String msg1 = “日期:2018-08-27”;
String msg2 = “异常:NullPointerException”;
String msg3 = “位置:Demo.java 13行”;
//使用匿名内部子类对象
printLog(2, new MessageBuilder() {
@Override
public String buildMsg() {
System.out.println(“开始拼接信息….”);
return msg1 + msg2 + msg3;
}
});
//使用Lambda代替
printLog(1,()-> msg1 + msg2 + msg3);
}

public static void printLog(int level, MessageBuilder mb) {
    if (level == 1) {
        System.out.println("写入日志:");
        System.out.println(mb.buildMsg());//调用方法,拼接字符串
    }else{
        System.out.println("不写日志:");
    //不调方法,不拼接字符串
    }
}

}

05.能够使用Lambda作为方法的参数
interface IA{
public void show();
}
public static void main(String[] args){
f1(()->System.out.println(“Hello”));
}
public static void f1(IA a){
a.show();
}
06.能够使用Lambda作为方法的返回值
public static void main(String[] args){
Runnable run = f1();
new Thread(run).start();
}
public static Runnable f1(){
return ()->System.out.println(“Lambda线程开始运行…”);
}

07.能够使用输出语句的方法引用
interface IA{
public void show(String s);
}
public static void main(String[] args){
//1.目标:打印:HelloWorld:使用Lambda的形式
f1((String s)-> System.out.println(s),”HelloWorld”);
// 由于:show(String s)方法就是:接收一个String 并打印。
// 类库中有个方法:System.out.println()可以做一样的操作
//2.使用System.out.println(String s)方法替换show(String s)
f1(System.out::println,”HelloWorld”);
}
public static void f1(IA a,String s){
a.show(s);
}
08.能够通过4种方式使用方法引用
1).静态方法引用
(类名::方法名)
2).类成员方法引用:
(new 对象()::方法名)

3).super和this引用:
4).  构造器引用:
    1).类构造器:Cat::new
    2).数组构造器;int[]::new

09.能够使用类和数组的构造器引用

10.能够使用Supplier函数式接口:生产者接口
public class Demo {
public static void main(String[] args) {
setSpl(()->{return “Hello”;});
setSplInteger(()-> {return 10;});

}


public static void setSpl(Supplier<String> spl) {
        System.out.println(spl.get());
}

public static void setSplInteger(Supplier<Integer> intSpl) {
    System.out.println("一个int值:" + intSpl.get());
}

}

11.能够使用Consumer函数式接口
public class Demo {
public static void main(String[] args) {
f1((s)-> System.out.println(s),”Hello”);

    f2((n)-> System.out.println(n),10);
}
public static void  f1(Consumer<String> c,String str){
    c.accept(str);

}

public static void f2(Consumer<Integer> c, Integer integer) {
    c.accept(integer);
}

}

版权声明:本文为zzz323666原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zzz323666/article/details/82114101

智能推荐

mybatis+ehcache二级缓存

导入jar包 mapper.xml文件开启二级缓存 pojo类实现序列化接口 配置ehcache.xml 测试...

python+opencv实现图像拼接

任务 拍摄两张图片去除相同部分,拼接在一起 原图 结果 步骤 读取两张图片 使用sift检测关键点及描述因子 匹配关键点 处理并保存关键点 得到变换矩阵 图像变换并拼接 代码实现 扩展 这里对右边图像进行变换,右边变得模糊,可以修改代码对左边图像变换 这里只有两张图片拼接,可以封装实现多张图片拼接 可以修改代码实现上下图片的拼接...

python_sklearn机器学习算法系列之AdaBoost------人脸识别(PCA,决策树)

          注:在读本文之前建议读一下之前的一片文章python_sklearn机器学习算法系列之PCA(主成分分析)------人脸识别(k-NearestNeighbor,KNN)         本文主要目的是通过一个简单的小...

memmove函数与memcpy函数的模拟实现

memmove函数和memcpy函数都是在内存复制任意类型的,但是它俩也有区别。当源区域和目标区域有重复的,memmove函数会复制缓冲区重叠的部分,而memcpy相反,会报出未知错误。 下面给出两个函数的实现 首先,memmove函数。 实现的基本原理如下图。 具体代码如下: memcpy函数的实现很简单,就直接给出源代码了...

猜你喜欢

SpringFramework核心 - IOC容器的实现 - 总结

1. 概述 把Spring技术内幕第一章和第二章过了一遍,也做了一些笔记, 对IOC容器的实现有了一定皮毛理解,现在跟着源码再过一遍总结一下IOC容器的初始化,Bean的初始化的过程,做一下总结 ① IOC容器和简单工厂模式 在开始之前,先想想我们平时是怎么使用IOC容器为我们管理Bean的,假设我们要把下面的User类交给IOC容器管理 我们不想关心如何创建一个User对象实例的,仅仅在需要他的...

Python和Django的安装

个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈  一、下载并安装Python Python 官方下载地址:http://www.python.org/ftp/python/ 我们这里选择的是 Python 2.7.2 。虽然目前最新版是Python 3.2.2, 但是Django目前还不支持 Python 3.2.2。 安装步骤很简单,双击安装包开...

OpenStack代码贡献初体验

为什么80%的码农都做不了架构师?>>>     OpenStack如今已成为开源云平台中的明星项目,得到广泛关注。OpenStack的优秀出众依赖于众多开发者的努力,在享受其带来的便利与快捷的同时,为其做一份贡献也是一个开发者的义务。  在前段时间的OpenStack的测试过程中,我发现Nova项目中的一个Bug,于是向社区提交了Bug报...

SQL Server之8:sql查询每个学生得分最高的两门课

这是一道面试题,今天有空把它记下来,以后遇到此类问题作个参考!刚一看到这个题目,估计好多人都会想到关键字top,其实这里用到的关键字是partition, 好了,先看看表结构,及数据吧!     接下来看一看partition的功能,执行语句   结果如下:   到这里一目了然知道最终结果了!   View Code     &...

vue-video-player 浏览器缩放

文章目录 前言 一、vue-video-player的封装 二、调用 1. 引入 2. vue template代码 2. 主要js代码 效果 前言 此篇是在上一次《[Vue 播放rtmp直播流]》基础之上的更新及补充;近期接到客户需求,需要在视频流上显示额外的信息;当然,视频流上叠加信息可以通过canvas来完成(透明canvas实现),但是在测试的过程中发现,当浏览器缩放时,叠加的图层信息与初...