八 JDK8新特性——第四节 方法引用-优化Lambda

1、方法引用基本介绍

主要对Lambda表达式的优化
在使用Lambda表达式的时候,实际上传递进去的是代码就是一种解决方案,拿什么参数做什么需求,那么考虑一种情况,如果我们在Lambda中所指的操作方案,已经有地方有相同方案,是否需重复?

Lambda要有函数式接口,定义一个函数式接口

package com.company.demo05LambdaTest;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:37
 * 定义一个打印的函数式接口,
 */
@FunctionalInterface
public interface Printable {
    //打印字符串的抽象方法
     void print(String s);
}

定义一个类。

package com.company.demo05LambdaTest;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:39
 */
public class Demo01Printable {
    //定义一个方法,参数传printable接口。对字符串打印
    public static void printString(Printable p ){
        p.print("helloword");
    }

    public static void main(String[] args) {
        //调用printstring方法 ,参数Printable是一个函数式接口,可以传递lambda表达式
        printString((s)->{
            System.out.println(s); //helloword
        });
        /*
 分析
        lambda 表达式的目的,打印参数传递的字符串,把参数s传递给System.out对象,调用out对象的方法println,对字符串输出
        注意:
        1、System.out对象已经存在,
        2、调用其方法println已经存在

       所以可以用方法引用优化lambda
       可以使用System.out直接引用(调用)println方法 ,取代Lambda, 对字符串输出,参数省略
       :: 是方法引用的运算符,表达式是方法引用表达式
       两种写法效果一样,第二种更简洁
       注意:
       Lambda中传递的参数一定是方法引用中的那个方法可以接收的类型,否则抛异常
         */
        printString(System.out::println);  //helloword
    }
}
方法引用符

2、方法引用-通过对象名引用成员方法

前提: 类存在,静态方法存在

1、对象名要有实例 化的对象,所以要建一个类,实例对象, 类中定义一个成员方法, 通过类创建一个对象,来引用里面的成员方法
类MethodRerObject

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 16:48
 */
public class MethodRerObject {

    //定义一个成员方法,传递字符串,按照大写输出
    public  void printUpString(String str){
        System.out.println(str.toUpperCase());
    }
}

2、函数式接口

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:37
 * 定义一个打印的函数式接口,
 */
@FunctionalInterface
public interface Printable {
    //打印字符串的抽象方法
     void print(String s);
}

3、测试类

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 16:51
 * 通过对象名引用成员方法
 * 使用前提:对象名存在,成员方法存在,就可以使用对象名引用成员方法
 */
public class Demo01ObjectMethodRer {
    //定义一个方法。方法的参数传递Printable接口
    public static void printString(Printable p){
        p.print("hello");
    }

    public static void main(String[] args) {
        //调用printString ,方法的参数是函数式接口,可以传递lambda 表达式
        printString((s)->{
            //创建MethodRerObject对象
            MethodRerObject obj = new MethodRerObject();
            //调用对象中的成员方法printUpString,把字符串按照大写输出
            obj.printUpString(s);  //HELLO
        });

        /*使用方法引用优化lambda
        对象MethodRerObject已经存在, 成员方法也存在printUpString
        所以可以用对象名来引用成员方法
         */
        //创建MethodRerObject对象
        MethodRerObject obj2 = new MethodRerObject();
        printString(obj2::printUpString);  //HELLO
    }
}

3、方法引用-通过类名引用静态成员方法

由于在类中java.lang.Math中已经存在了静态方法abs,所以需要通过lambda 调用该方法时,有两种写法,首先是函数式接口,使用lambda , 一种是类名引用静态方法

函数式接口

package com.company.demo07StaticMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 17:08
 */
@FunctionalInterface
public interface Calcable {
    //定义一个抽象方法,传递一个整数,对整数进行绝对值计算,并返回
    public int calAbs(int number);
}

测试类

package com.company.demo07StaticMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 17:11
 * 通过类名引用静态成员方法,使用前提:类名存在,静态成员方法存在;就可以直接用类名引用静态成员方法
 */
public class Demo01StaticMethodRer {
   //定义一个方法,方法的参数传递要计算绝对值的整数 和 函数式接口Calcable
    public static int method(int number,Calcable c){
        return c.calAbs(number);
    }

    public static void main(String[] args) {
        //调用method 方法,传递计算绝对值的整数 和 Lambda表达式
        int num = method(-10,(n)->{
            //对参数进行绝对值的计算,并返回结果
            return Math.abs(n);
        });
        System.out.println(num);  //10

        /*通过类名引用静态成员方法。优化lambda表达式
        Math 存在。abs 计算绝对值的静态成员方法存在
        所以可以直接通过类名引用静态方法
         */
        int num2 = method(-10, Math::abs);
        System.out.println(num2);  //10

    }
}

4、方法引用-通过super引用父类的成员方法

如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代
前提: 有子父类继承关系,有函数式接口,父类有成员方法


例子

函数式接口

package con.day13.demo05.SuperMethodReference;

/*
定义一个见面的函数式接口
 */
@FunctionalInterface
public interface Greetable {
   //定义一个见面的方法
    void greet();
}

父类

package con.day13.demo05.SuperMethodReference;

/*
定义父类
 */
public class Human {
    //定义一个sayhello 的方法
    public void sayHello(){
        System.out.println("父类human的sayHellO");
    }
}

子类以及主方法

package con.day13.demo05.SuperMethodReference;
/*
定义子类
 */
public class Man extends Human{
    //重写父类sayHello的方法

    @Override
    public void sayHello() {
        System.out.println("我是子类");
    }

    //定义一个方法参数传递Greetable接口
    public void method(Greetable g){
        g.greet();
    }

    public void show(){
        //调用method 方法,方法的参数是函数式接口,可传递Lambda
       /* method(()->{
            //创建父类对象
            Human h = new Human();
            //调用父类的sayHello
            h.sayHello();
        });*/
        //因为有子父类关系,可以存在一个关键字super 所以我们可以直接用super调用父类的成员方法

       /* method(()->{
            super.sayHello();    //父类human的sayHellO
        });*/

        //继续简化, 使用super引用父类的成员方法, super 已经存在,sayHello 已经存在,
        //所以可直接使用super引用父类的成员方法
        //父类human的sayHellO
        method(super::sayHello);
    }

    public static void main(String[] args) {
        new Man().show();  //父类human的sayHellO
    }
}

5、方法引用,通过this引用本类的成员

this

函数式接口

package con.day13.demo05.ThisMethodReference;

/*
定义一个函数式接口
 */
@FunctionalInterface
    public interface Richable {
        //想买什么就买什么的方法
        void buy();
    }

方法:

package con.day13.demo05.ThisMethodReference;

/*
通过this引用本类的成员方法
 */
public class Husband {
    //定义一个买房子的方法
    public void buyHouse(){
        System.out.println("买到房子啦");
    }
    //定义结婚方法,参数传递Richable接口
    public void marry(Richable r){
        r.buy();
    }

/*    //定义一个非常高兴的方法
    public void soHappy(){
        //调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
        marry(()->{
            //使用this.成员方法,调用本类买房子的方法
            this.buyHouse();  //买到房子啦
        });
    }*/

    //简化, 方法引用

    //定义一个非常高兴的方法
    public void soHappy(){
        //调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
        marry(this::buyHouse);  //买到房子啦;
    }


    public static void main(String[] args) {
        Husband husband = new Husband();
        husband.soHappy();
    }
}

6、 方法引用-类的构造器引用

Person 类

package con.day13.demo05.ConstructorMethodReference;

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

函数式接口

package con.day13.demo05.ConstructorMethodReference;
//创建Perso对象的函数式接口
@FunctionalInterface
public interface PersonBuilder {
    //定义一个方法,根据传递的姓名,创建Person 对象返回
    Person builderPerson(String name);
}

方法类

package con.day13.demo05.ConstructorMethodReference;

/*
类的构造器引用
 */
public class Demo {
    //定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
    public static void pringName(String name, PersonBuilder pb){
        Person person = pb.builderPerson(name);
        System.out.println(person.getName()); //迪丽热巴
    }

/*    public static void main(String[] args) {
        //调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
        pringName("迪丽热巴",(String name)->{
            return new Person(name);
        });
    }*/
/*使用方法引用,优化
构造方法new Person(String name)已知
创建对象已经new
就可以使用Person引用new创建对象
    */
    public static void main(String[] args) {
        //调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
        pringName("迪丽热巴", Person::new);
    }
}

7、方法引用-数组的构造引用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容