亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java8中雙冒號::的使用方法

發布時間:2020-11-03 15:36:55 來源:億速云 閱讀:383 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關Java8中雙冒號::的使用方法,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

一、方法引用

java8允許我們使用lambda表達式創建匿名方法。但有時lambda表達式除了調用現有方法之外什么也不做。在這些情況下,通過名稱引用現有的方法,通常能更直白的表現出方法的調用過程。對于已經存在的且具有方法名稱的方法,它其實是簡潔且易于讀取的一種lambda表達式,或者說是對lambda表達式的一種進一步簡化。

現在我們來看看下面這個“person”類:

public class Person {

  public enum Sex {
    MALE, FEMALE
  }

  String name;
  LocalDate birthday;
  Sex gender;
  String emailAddress;

  public int getAge() {
    // ...
  }
  
  public Calendar getBirthday() {
    return birthday;
  }  

  public static int compareByAge(Person a, Person b) {
    return a.birthday.compareTo(b.birthday);
  }}

假設你的社交網絡應用程序的成員包含在一個數組中,并且你希望按年齡對數組進行排序。你可以使用以下代碼:

Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);

class PersonAgeComparator implements Comparator<Person> {
  public int compare(Person a, Person b) {
    return a.getBirthday().compareTo(b.getBirthday());
  }
}
    
Arrays.sort(rosterAsArray, new PersonAgeComparator());

上面最后一行代碼:Java8中雙冒號::的使用方法中的sort方法源碼如下:

static <T> void sort(T[] a, Comparator<&#63; super T> c)

注意,接口comparator是一個功能接口。因此,你可以使用lambda表達式,而不是定義并創建實現comparator的類的新實例,所以上上面的代碼可以用lambda表達式改寫成下面這樣:

Arrays.sort(rosterAsArray,  (Person a, Person b) -> {    return a.getBirthday().compareTo(b.getBirthday());  });

但是,我們已經在Person bean對象中提前寫好了用來比較兩個person對象的出生日期的方法:Java8中雙冒號::的使用方法,所以你其實可以在lambda表達式的主體中直接調用這個方法方法:

Arrays.sort(rosterAsArray,
  (Person a, Person b) -> {
    return a.getBirthday().compareTo(b.getBirthday());
  }
);

因為這個上面這個lambda表達式是在調用現有的方法,所以我們這里就可以使用上面提到的使用方法引用方式(及雙冒號 ::),而不是之前我們熟悉的lambda表達式:

Arrays.sort(rosterAsArray, Person::compareByAge);

方法引用 person::comparebyage 在語義上與lambda表達式(a,b)->person.comparebyage(a,b)相同。他們都有以下特點:

  • 它的形參列表復制自comparator<person>.compare,即(Person, Person)
  • 它的主體調用方法是:person.comparebyage。

二、方法引用的種類(哪些場景可以使用方法引用)

有四種方法引用:

種類

案例
引用靜態方法ContainingClass::staticMethodName
對特定對象的實例方法的引用containingObject::instanceMethodName
對特定類型的任意對象的實例方法的引用ContainingType::methodName
對構造函數的引用ClassName::new

1、引用靜態方法

例如:

Person::comparebyage 是對Person類的靜態方法 comparebyage 的引用。

2、引用特定對象的實例方法

以下是對特定對象的實例方法的引用示例:

class ComparisonProvider {
  public int compareByName(Person a, Person b) {
    return a.getName().compareTo(b.getName());
  }
    
  public int compareByAge(Person a, Person b) {
    return a.getBirthday().compareTo(b.getBirthday());
  }
}
ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

方法引用   myComparisonProvider::compareByName 調用對象myComparisonProvider的一部分方法 compareByName。然后JRE會自動推斷方法類型參數,在這種情況下為(Person, Person)

3、引用特定類型的任意對象的實例方法

以下是對特定類型的任意對象的實例方法的引用示例:

String[] stringArray = { 
  "Barbara", "James", "Mary", "John",
  "Patricia", "Robert", "Michael", "Linda"
 };

Arrays.sort(stringArray, String::compareToIgnoreCase);

方法引用  string::compareTogignoreCase  的等效lambda表達式會有形參列表(String a,String b),其中a和b是用于更好地描述此示例的任意名稱。這次的方法引用,將調用方法a.CompareTognoreCase(b)。

這里官網原文可能說的不是很清楚,也有點拗口,多說一句:

如何理解:對特定類型的 任意對象的 實例方法的引用  這句話呢?

實際上上面代碼沒有在特定實例(也就是沒有new一個指定的String 實例出來,像這樣:String s = new String() ,s就是一個指定的String對象的實例)上引用方法 compareTogignoreCase ,而是在String類自身引用的。

我們進入Arrays.sort(xx,xx)方法源碼,我們可以看到這個數組排序方法底層算法涉及循環,那么Java8中雙冒號::的使用方法這行代碼我們可以想象它會在每循環到數組的一個String元素時,以這個String元素所屬類型對象(其實就是String對象)的身份去調用compareTogignoreCase方法,即:

Java8中雙冒號::的使用方法會調用Java8中雙冒號::的使用方法的compareTogignoreCase   --》String Barbara = new String(); Barbara.compareTogignoreCase   

Java8中雙冒號::的使用方法會調用Java8中雙冒號::的使用方法的compareTogignoreCase  --》String James= new String();James.compareTogignoreCase  

以此類推。。。

我可能解釋的也不太好,主要就是想語言上理解一下:對特定類型的 任意對象的 實例方法 的引用

Java8中雙冒號::的使用方法

4、引用構造函數

你可以通過使用name new 的方式引用構造函數,這與靜態方法的引用方式類似。

下面這個示例方法,是將元素從一個集合復制到另一個集合。我們將以這個方法為例,講解如何使用方法引用的方式引用構造函數。

public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
  DEST transferElements(SOURCE sourceCollection,Supplier<DEST> collectionFactory) {
    
    DEST result = collectionFactory.get();

    for (T t : sourceCollection) {
      result.add(t);
    }

    return result;
}

函數接口supplier包含一個無參但返回一個對象的get方法,源碼可見,他返回的類型就是泛型的類型,如下:

Java8中雙冒號::的使用方法

因此,可以使用lambda表達式調用方法transferElements,如下所示:

Set<Person> rosterSetLambda =
  transferElements(roster, () -> { return new HashSet<>(); });

可以使用構造函數引用代替lambda表達式,如下所示:

Set<Person> rosterSet = transferElements(roster, HashSet::new);

上面代碼,Java編譯器執行的時候會自動推斷出這里想要創建一個包含Person類型元素的hashset集合。當然你也可以顯示的指定類型,如下:

Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);

關于Java8中雙冒號::的使用方法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

即墨市| 莱州市| 瑞金市| 阿克苏市| 揭阳市| 泾川县| 枣阳市| 临沧市| 罗山县| 石棉县| 灵宝市| 饶平县| 上思县| 年辖:市辖区| 清远市| 保亭| 沁阳市| 乌兰浩特市| 潍坊市| 双鸭山市| 大城县| 建水县| 岗巴县| 柘城县| 梨树县| 永昌县| 汶上县| 辛集市| 广水市| 亚东县| 图们市| 蒲城县| 德州市| 武鸣县| 华坪县| 陵水| 专栏| 东辽县| 福建省| 洪泽县| 尚志市|