方法引用

  • 在使用Lambda表達式的時候喘落,我們實際上傳遞進去的代碼就是一種解決方案:拿什么參數(shù)做什么操作。那么考慮一種情況:如果我們在Lambda中所指定的操作方案蟹倾,已經有地方存在相同方案匣缘,那是否還有必要再寫重復邏輯?
  • 用方法引用改進Lambda表達式鲜棠,雙冒號 :: 寫法肌厨,這被稱為“方法引用”,而雙冒號是一種新的語法豁陆。
  • 如果Lambda要表達的函數(shù)方案已經存在于某個方法的實現(xiàn)中柑爸,那么則可以通過雙冒號來引用該方法作為Lambda的替代者。
public class Demo01Printable {
    //定義一個方法,參數(shù)傳遞Printable接口,對字符串進行打印
    public static void printString(Printable p) {
        p.print("HelloWorld");
    }

    public static void main(String[] args) {
        //調用printString方法,方法的參數(shù)Printable是一個函數(shù)式接口,所以可以傳遞Lambda
        printString((s) -> {
            System.out.println(s);
        });

        /*
            分析:
                Lambda表達式的目的,打印參數(shù)傳遞的字符串
                把參數(shù)s,傳遞給了System.out對象,調用out對象中的方法println對字符串進行了輸出
                注意:
                    1.System.out對象是已經存在的
                    2.println方法也是已經存在的
                所以我們可以使用方法引用來優(yōu)化Lambda表達式
                可以使用System.out方法直接引用(調用)println方法
         */
        printString(System.out::println);
    }
}
/*
    定義一個打印的函數(shù)式接口
 */
@FunctionalInterface
public interface Printable {
    //定義字符串的抽象方法
    void print(String s);
}

1. 通過對象名引用成員方法

/*
    通過對象名引用成員方法
    使用前提是對象名是已經存在的,成員方法也是已經存在
    就可以使用對象名來引用成員方法
 */
public class Demo01ObjectMethodReference {
    //定義一個方法,方法的參數(shù)傳遞Printable接口
    public static void printString(Printable p){
        p.print("Hello");
    }

    public static void main(String[] args) {
        //調用printString方法,方法的參數(shù)Printable是一個函數(shù)式接口,所以可以傳遞Lambda表達式
        printString((s)->{
            //創(chuàng)建MethodRerObject對象
            MethodRerObject obj = new MethodRerObject();
            //調用MethodRerObject對象中的成員方法printUpperCaseString,把字符串按照大寫輸出
            obj.printUpperCaseString(s);
        });

        /*
            使用方法引用優(yōu)化Lambda
            對象是已經存在的MethodRerObject
            成員方法也是已經存在的printUpperCaseString
            所以我們可以使用對象名引用成員方法
         */
        //創(chuàng)建MethodRerObject對象
        MethodRerObject obj = new MethodRerObject();
        printString(obj::printUpperCaseString);
    }
}

public class MethodRerObject {
    //定義一個成員方法,傳遞字符串,把字符串按照大寫輸出
    public void printUpperCaseString(String str){
        System.out.println(str.toUpperCase());
    }
}
/*
    定義一個打印的函數(shù)式接口
 */
@FunctionalInterface
public interface Printable {
    //定義字符串的抽象方法
    void print(String s);
}

2. 通過類名稱引用靜態(tài)方法

@FunctionalInterface
public interface Calcable {
    //定義一個抽象方法,傳遞一個整數(shù),對整數(shù)進行絕對值計算并返回
    int calsAbs(int number);
}

/*
    通過類名引用靜態(tài)成員方法
    類已經存在,靜態(tài)成員方法也已經存在
    就可以通過類名直接引用靜態(tài)成員方法
 */
public class Demo01StaticMethodReference {
    //定義一個方法,方法的參數(shù)傳遞要計算絕對值的整數(shù),和函數(shù)式接口Calcable
    public static int method(int number,Calcable c){
       return c.calsAbs(number);
    }

    public static void main(String[] args) {
        //調用method方法,傳遞計算絕對值得整數(shù),和Lambda表達式
        int number = method(-10,(n)->{
            //對參數(shù)進行絕對值得計算并返回結果
            return Math.abs(n);
        });
        System.out.println(number);

        /*
            使用方法引用優(yōu)化Lambda表達式
            Math類是存在的
            abs計算絕對值的靜態(tài)方法也是已經存在的
            所以我們可以直接通過類名引用靜態(tài)方法
         */
        int number2 = method(-10,Math::abs);
        System.out.println(number2);
    }
}

3. 通過super引用成員方法

/*
    定義父類
 */
public class Human {
    //定義一個sayHello的方法
    public void sayHello(){
        System.out.println("Hello 我是Human!");
    }
}

/*
    定義子類
 */
public class Man extends Human{
    //子類重寫父類sayHello的方法
    @Override
    public void sayHello() {
        System.out.println("Hello 我是Man!");
    }

    //定義一個方法參數(shù)傳遞Greetable接口
    public void method(Greetable g){
        g.greet();
    }

    public void show(){
        //調用method方法,方法的參數(shù)Greetable是一個函數(shù)式接口,所以可以傳遞Lambda
        /*method(()->{
            //創(chuàng)建父類Human對象
            Human h = new Human();
            //調用父類的sayHello方法
            h.sayHello();
        });*/

        //因為有子父類關系,所以存在的一個關鍵字super,代表父類,所以我們可以直接使用super調用父類的成員方法
       /* method(()->{
            super.sayHello();
        });*/

      /*
           使用super引用類的成員方法
           super是已經存在的
           父類的成員方法sayHello也是已經存在的
           所以我們可以直接使用super引用父類的成員方法
       */
      method(super::sayHello);
    }

    public static void main(String[] args) {
        new Man().show();
    }
}

/*
    定義見面的函數(shù)式接口
 */
@FunctionalInterface
public interface Greetable {
    //定義一個見面的方法
    void greet();
}

4. 通過this引用成員方法

/*
    定義一個富有的函數(shù)式接口
 */
@FunctionalInterface
public interface Richable {
    //定義一個想買什么就買什么的方法
    void buy();
}

/*
    使用this引用本類的成員方法
 */
public class Husband {
    //定義一個買房子的方法
    public void buyHouse(){
        System.out.println("北京二環(huán)內買一套四合院!");
    }

    //定義一個結婚的方法,參數(shù)傳遞Richable接口
    public void marry(Richable r){
        r.buy();
    }

    //定義一個非常高興的方法
    public void soHappy(){
        //調用結婚的方法,方法的參數(shù)Richable是一個函數(shù)式接口,傳遞Lambda表達式
       /* marry(()->{
            //使用this.成員方法,調用本類買房子的方法
            this.buyHouse();
        });*/

        /*
            使用方法引用優(yōu)化Lambda表達式
            this是已經存在的
            本類的成員方法buyHouse也是已經存在的
            所以我們可以直接使用this引用本類的成員方法buyHouse
         */
        marry(this::buyHouse);
    }

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

5. 類的構造器引用

/*
    定義一個創(chuàng)建Person對象的函數(shù)式接口
 */
@FunctionalInterface
public interface PersonBuilder {
    //定義一個方法,根據(jù)傳遞的姓名,創(chuàng)建Person對象返回
    Person builderPerson(String name);
}
public class Person {
    private String name;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

/*
    類的構造器(構造方法)引用
 */
public class Demo {
    //定義一個方法,參數(shù)傳遞姓名和PersonBuilder接口,方法中通過姓名創(chuàng)建Person對象
    public static void printName(String name,PersonBuilder pb){
        Person person = pb.builderPerson(name);
        System.out.println(person.getName());
    }

    public static void main(String[] args) {
        //調用printName方法,方法的參數(shù)PersonBuilder接口是一個函數(shù)式接口,可以傳遞Lambda
        printName("迪麗熱巴",(String name)->{
            return new Person(name);
        });

        /*
            使用方法引用優(yōu)化Lambda表達式
            構造方法new Person(String name) 已知
            創(chuàng)建對象已知 new
            就可以使用Person引用new創(chuàng)建對象
         */
        printName("古力娜扎",Person::new);//使用Person類的帶參構造方法,通過傳遞的姓名創(chuàng)建對象
    }
}

6. 數(shù)組的構造器引用

/*
    數(shù)組的構造器引用
 */
public class Demo {
    /*
        定義一個方法
        方法的參數(shù)傳遞創(chuàng)建數(shù)組的長度和ArrayBuilder接口
        方法內部根據(jù)傳遞的長度使用ArrayBuilder中的方法創(chuàng)建數(shù)組并返回
     */
    public static int[] createArray(int length, ArrayBuilder ab){
        return  ab.builderArray(length);
    }

    public static void main(String[] args) {
        //調用createArray方法,傳遞數(shù)組的長度和Lambda表達式
        int[] arr1 = createArray(10,(len)->{
            //根據(jù)數(shù)組的長度,創(chuàng)建數(shù)組并返回
            return new int[len];
        });
        System.out.println(arr1.length);//10

        /*
            使用方法引用優(yōu)化Lambda表達式
            已知創(chuàng)建的就是int[]數(shù)組
            數(shù)組的長度也是已知的
            就可以使用方法引用
            int[]引用new,根據(jù)參數(shù)傳遞的長度來創(chuàng)建數(shù)組
         */
        int[] arr2 =createArray(10,int[]::new);
        System.out.println(Arrays.toString(arr2));
        System.out.println(arr2.length);//10
    }
}

/*
    定義一個創(chuàng)建數(shù)組的函數(shù)式接口
 */
@FunctionalInterface
public interface ArrayBuilder {
    //定義一個創(chuàng)建int類型數(shù)組的方法,參數(shù)傳遞數(shù)組的長度,返回創(chuàng)建好的int類型數(shù)組
    int[] builderArray(int length);
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末盒音,一起剝皮案震驚了整個濱河市表鳍,隨后出現(xiàn)的幾起案子馅而,更是在濱河造成了極大的恐慌,老刑警劉巖譬圣,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓮恭,死亡現(xiàn)場離奇詭異,居然都是意外死亡厘熟,警方通過查閱死者的電腦和手機偎血,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盯漂,“玉大人颇玷,你說我怎么就攤上這事【屠拢” “怎么了帖渠?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竭宰。 經常有香客問我空郊,道長,這世上最難降的妖魔是什么切揭? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任狞甚,我火速辦了婚禮,結果婚禮上廓旬,老公的妹妹穿的比我還像新娘哼审。我一直安慰自己,他們只是感情好孕豹,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布涩盾。 她就那樣靜靜地躺著,像睡著了一般励背。 火紅的嫁衣襯著肌膚如雪春霍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天叶眉,我揣著相機與錄音址儒,去河邊找鬼。 笑死衅疙,一個胖子當著我的面吹牛莲趣,可吹牛的內容都是我干的。 我是一名探鬼主播炼蛤,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼妖爷,長吁一口氣:“原來是場噩夢啊……” “哼蝶涩!你這毒婦竟也來了理朋?” 一聲冷哼從身側響起絮识,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗽上,沒想到半個月后次舌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡兽愤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年彼念,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浅萧。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡逐沙,死狀恐怖,靈堂內的尸體忽然破棺而出洼畅,到底是詐尸還是另有隱情吩案,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布帝簇,位于F島的核電站徘郭,受9級特大地震影響,放射性物質發(fā)生泄漏丧肴。R本人自食惡果不足惜残揉,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芋浮。 院中可真熱鬧抱环,春花似錦、人聲如沸纸巷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽何暇。三九已至陶夜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裆站,已是汗流浹背条辟。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宏胯,地道東北人羽嫡。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像肩袍,于是被迫代替她去往敵國和親杭棵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348