Android 使用Java8新特性之"方法引用"

來源:互聯網
上載者:User

標籤:parse   安卓   express   int   工具類   命令   配置   rip   傳值   

前言

上一文:Android 使用Java8新特性之Lambda expression (附命令者模式簡化)
說過lambda運算式,在android studio中的環境配置及應用。本文講下Java8新特性之”方法引用”。
“方法引用”,它其實可以看成lambda運算式的一種簡寫形式。
再回顧一下lambda運算式的應用情境:簡化僅含單一抽象方法介面的調用

方法引用的4種形式

方法引用的符號形式,形如,
[className | class-instance]::[static-method | instance-method | construct-method]
即,以類名或類的執行個體對象為首碼,中間以兩個冒號(::)串連,後跟靜態方法 或 執行個體方法 或 構造方法

分類:
1. 靜態方法引用
2. 執行個體方法引用
3. 類執行個體方法引用
4. 構造方法引用

靜態方法引用

類MethodReferenceActivity下有一靜態方法:

static int parz(String str) {//被lambda運算式或"方法引用"調用   return Integer.parseInt(str);}

如果直接調用 MethodReferenceActivity::parz當然是不行的,因為”方法引用”是用來替換lambda運算式的,所以也將指代一個僅含單一抽象方法的介面

再有一個介面:

public interface ToIntFunc<T> {//註:原生jdk中就有的方法,安卓中沒有    int applyAsInt(T value);}

再有一個使用ToIntFunc介面的靜態方法:

public static int parse(ToIntFunc<String> f, String num) {   return f.applyAsInt(num);}

調用parse()時使用lambda運算式:

int parseValue = parse((value -> parz(value)), num);

調用parse()時使用”方法引用”:

int parseValue = parse(MethodReferenceActivity::parz, num);
執行個體方法引用

將上面的方法parse方法聲明中的static 去掉:

public int parse(ToIntFunc<String> f, String num) {   return f.applyAsInt(num);}

調用parse()時使用”方法引用”:

int parseValue = parse(this::parz, num); //this指當前類的執行個體對象
類執行個體方法引用需要在外部調用方法中,聲明參數

如有一個內部類Person:

static class Person {    public Person() {    }    public Person(String name) {        this.name = name;    }    String name;    Long birthday;    public Long getBirthday() {        return birthday;    }    public String getName() {        return name;    }    public boolean compareByName(Person b) {        int result = this.name.compareToIgnoreCase(b.name);        if (result == 1) {            return true;        } else {            return false;        }    }    @Override    public String toString() {        return "Person{" +                "name=‘" + name + ‘\‘‘ +                ", birthday=" + birthday +                ‘}‘;    }    public void printInfo() {        System.out.println(toString());    }}

有一個介面Compare:

public interface Compare<T> {    boolean compareTo(T v1, T v2);}

外部的使用介面Compare的調用方法isLarge:

public boolean isLarge(Compare<Person> c, Person p1, Person p2) {    return c.compareTo(p1, p2);}

使用lambda運算式和類執行個體方法引用:

Person p1 = new Person("stone");Person p2 = new Person("sun");boolean result = isLarge((v1, v2) -> v1.compareByName(v2), p1, p2);System.out.println("p1 排序在 p2 後: " + result);result = isLarge(Person::compareByName, p1, p2);System.out.println("p1 排序在 p2 後: " + result);

這裡isLarge方法,除介面外,還要求傳遞兩個Person的執行個體對象。這兩個對象,被Compare介面中的compareTo方法使用。

不需要在外部調用方法中,聲明參數

再來看如下一組代碼:

Integer[] ary = {2, 8, 1, 5, 6, 3, 4};Arrays.sort(ary, (o1, o2) -> o1.compareTo(o2));Arrays.sort(ary, Integer::compareTo);

這是調用數組工具類Arrays.sort()來進行排序。
在【Arrays.sort(ary, Integer::compareTo);】中,”類執行個體方法引用”實際指代java.util.Comparator介面,介面中的靜態方法為:int compare(T o1, T o2);而這裡並沒有傳遞o1、o2參數。o1,o2的執行個體化,實際上是在sort方法內部完成的。 就好比如下樣本,

/**內部執行個體化*/public boolean isLarge(Compare<Person> c) {    Person p1 = new Person("stone");    Person p2 = new Person("austin");    return c.compareTo(p1, p2);}

使用lambda和類執行個體方法引用:

isLarge((v1, v2) -> v1.compareByName(v2));//lambda expressionisLarge(Person::compareByName);//method reference
構造方法引用

現有下面的代碼:

static class Person {    String name;    public Person() {    }    public Person(String name) {        this.name = name;    }}public interface GetType<T> {    T get(String value);}public interface GetType2<T> {    T get();}public Person getPerson(String name, GetType<Person> data) {    return data.get(name);}public Person getPerson(GetType2<Person> data) {    return data.get();}

使用lambda和構造方法引用:

getPerson("li si", value -> new Person(value));//lambda//會調用new Person(String name)     指代GetTypegetPerson("zhang san", Person::new);getPerson(() -> new Person());//lambdagetPerson(Person::new);//會調用new Person()   指代GetType2
總結

不管是lambda運算式,還是”方法引用”,它們都指代一個僅含單一抽象方法介面的匿名內部類執行個體。使用”方法引用”後,一看錶達式,就能猜出方法引用的類別。同時配合AS,看調用方法的介面。
“方法引用”運算式的傳回值與介面中方法的傳回值一致。”方法引用”運算式所調用方法的參數,可以通過外部調用方法來傳值。如果有參數,而沒傳值,可能在外部方法內部進行了初始化,如”類執行個體方法引用”第二個樣本。

lambda運算式,是可以有一個方法體的。現在有了”方法引用”,就不用看起來那麼”混亂”了。比如:

button.setOnTouchListener((view, event)-> {    if (event.getAction() == MotionEvent.ACTION_DOWN) {        //do sth.        return true;    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {        //do sth.        return true;    }    return super.onTouchEvent(event);});

只需要聲明一個方法:

private boolean handleEvent(View v, MotionEvent event) {    //do sth.    return true;}

如下使用”方法引用”調用:

button.setOnTouchListener(this::handleEvent);

Android 使用Java8新特性之"方法引用"

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.